diff --git a/BKPS/14040626/Classes/x-saherelm.base.class.mq5 b/BKPS/14040626/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..a017ec3 --- /dev/null +++ b/BKPS/14040626/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: " + ToXString(mItem.period) + separator + + "Time: " + ToXString(mItem.time) + separator + + (includeScores + ? "---------------" + separator + + "Scores:" + separator + + "---------------" + separator + + "Bullish: " + ToXString(bullishScore) + separator + + "Bearish: " + ToXString(bearishScore) + separator + + "---------------" + separator + : "") + + "" + // + ; + + // + return result; +} + +// diff --git a/BKPS/14040626/Classes/x-saherelm.x-account.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-account.class.mq5 new file mode 100644 index 0000000..c451091 --- /dev/null +++ b/BKPS/14040626/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/14040626/Classes/x-saherelm.x-alert.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-alert.class.mq5 new file mode 100644 index 0000000..4c06900 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-alert.class.mq5 @@ -0,0 +1,1438 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAlert +// Description: provides all Alerts requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-data.collector.class.mq5" + +// +// Class Definition ... + +class XCAlert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCAlert( + string prefix = "X-Alert", // Alerts Prefixe + bool enableAlerts = true, // Enable Alerts + bool logAlerts = true, // Log Alerts + bool terminalAlerts = false, // Terminal Alerts + bool mailAlerts = false, // Mail Alerts + bool pushAlerts = false, // Push Alerts + bool saveAlerts = false // Save Alerts + ) + { + // + mPrefix = prefix; + mLogAlerts = logAlerts; + mMailAlerts = mailAlerts; + mPushAlerts = pushAlerts; + mSaveAlerts = saveAlerts; + mEnableAlerts = enableAlerts; + mTerminalAlerts = terminalAlerts; + + // + // Normalize Prefix if Not Provided ... + if (!IsValid(mPrefix)) + { + mPrefix = GetTag(); + } + + // + // Initialize Collector ... + collector = new XCDataCollector(); + collector.Path(mPrefix); + } + + // + // Deconstructor ... + ~XCAlert() + { + // + // Cleanup Resources ... + delete collector; + ZeroMemory(collector); + } + + // + // Override ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Properties Getter(s) / Setter(s) ... + + // + string GetPrefix() + { + return mPrefix; + } + + // + void SetPrefix(string value) + { + // + mPrefix = value; + collector.Path(mPrefix); + } + + // + bool GetLogAlerts() + { + return mLogAlerts; + } + + // + void SetLogAlerts(bool value) + { + mLogAlerts = value; + } + + // + bool GetEnableAlerts() + { + return mEnableAlerts; + } + + // + void SetEnableAlerts(bool value) + { + mEnableAlerts = value; + } + + // + bool GetSaveAlerts() + { + return mSaveAlerts; + } + + // + void SetSaveAlerts(bool value) + { + mSaveAlerts = value; + } + + // + bool GetPushAlerts() + { + return mPushAlerts; + } + + // + void SetPushAlerts(bool value) + { + mPushAlerts = value; + } + + // + bool GetMailAlerts() + { + return mMailAlerts; + } + + // + void SetMailAlerts(bool value) + { + mMailAlerts = value; + } + + // + bool GetTerminalAlerts() + { + return mTerminalAlerts; + } + + // + void SetTerminalAlerts(bool value) + { + mTerminalAlerts = value; + } + + // + // Tools Funtions ... + + // + // Alerts ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + // + // Validate Args ... + if (!CanLogAlert()) + { + return; + } + + // + message = PrepareMessage(message); + + // + Log(message); + Save(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + // + // Validate Args ... + if (!CanTerminalAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // Send Terminal Alert ... + Alert(message); + Save(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + // + // Validate Args ... + if (!CanMailAlert()) + { + return; + } + + // + // Send Mail Alert ... + SendMail(GetPrefix(), message); + Save(message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + // + // Validate Args ... + if (!CanPushAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); + Save(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void SendAlert(string message) + { + // + // Handle Log, if Enabled ... + LogAlert(message); + + // + // Handle Mail if Enabled ... + MailAlert(message); + + // + // Handle Push if Enabled ... + PushAlert(message); + + // + // Handle Terminal if Enabled ... + TerminalAlert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(message); + } + void Log(string tag, string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), "_", tag, " > ", message); + } + void LogEmpty() + { + // + if (!CanLog()) + { + return; + } + + // + Print(" "); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), ">", (IsValid(label) ? label : "")); + ArrayPrint(array); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + // + if (!CanLog()) + { + return; + } + + // + if (error <= -1) + { + error = GetLastError(); + } + + // + string errorMsg = GetErrorDescription(error); + + // + Log("Error: " + errorMsg); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + // + string result = ""; + + // + switch (err_code) + { + // + //--- Constant Description + + // + case ERR_SUCCESS: + result = "The operation completed successfully"; + break; + + // + case ERR_INTERNAL_ERROR: + result = "Unexpected internal error"; + break; + + // + case ERR_WRONG_INTERNAL_PARAMETER: + result = "Wrong parameter in the inner call of the client terminal function"; + break; + + // + case ERR_INVALID_PARAMETER: + result = "Wrong parameter when calling the system function"; + break; + + // + case ERR_NOT_ENOUGH_MEMORY: + result = "Not enough memory to perform the system function"; + break; + + // + case ERR_STRUCT_WITHOBJECTS_ORCLASS: + result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"; + break; + + // + case ERR_INVALID_ARRAY: + result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array"; + break; + + // + case ERR_ARRAY_RESIZE_ERROR: + result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"; + break; + + // + case ERR_STRING_RESIZE_ERROR: + result = "Not enough memory for the relocation of string"; + break; + + // + case ERR_NOTINITIALIZED_STRING: + result = "Not initialized string"; + break; + + // + case ERR_INVALID_DATETIME: + result = "Invalid date and/or time"; + break; + + // + case ERR_ARRAY_BAD_SIZE: + result = "Requested array size exceeds 2 GB"; + break; + + // + case ERR_INVALID_POINTER: + result = "Wrong pointer"; + break; + + // + case ERR_INVALID_POINTER_TYPE: + result = "Wrong type of pointer"; + break; + + // + case ERR_FUNCTION_NOT_ALLOWED: + result = "System function is not allowed to call"; + break; + + // + //--- Charts + + // + case ERR_CHART_WRONG_ID: + result = "Wrong chart ID"; + break; + + // + case ERR_CHART_NO_REPLY: + result = "Chart does not respond"; + break; + + // + case ERR_CHART_NOT_FOUND: + result = "Chart not found"; + break; + + // + case ERR_CHART_NO_EXPERT: + result = "No Expert Advisor in the chart that could handle the event"; + break; + + // + case ERR_CHART_CANNOT_OPEN: + result = "Chart opening error"; + break; + + // + case ERR_CHART_CANNOT_CHANGE: + result = "Failed to change chart symbol and period"; + break; + + // + case ERR_CHART_CANNOT_CREATE_TIMER: + result = "Failed to create timer"; + break; + + // + case ERR_CHART_WRONG_PROPERTY: + result = "Wrong chart property ID"; + break; + + // + case ERR_CHART_SCREENSHOT_FAILED: + result = "Error creating screenshots"; + break; + + // + case ERR_CHART_NAVIGATE_FAILED: + result = "Error navigating through chart"; + break; + + // + case ERR_CHART_TEMPLATE_FAILED: + result = "Error applying template"; + break; + + // + case ERR_CHART_WINDOW_NOT_FOUND: + result = "Subwindow containing the indicator was not found"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_ADD: + result = "Error adding an indicator to chart"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_DEL: + result = "Error deleting an indicator from the chart"; + break; + + // + case ERR_CHART_INDICATOR_NOT_FOUND: + result = "Indicator not found on the specified chart"; + break; + + // + //--- Graphical Objects + case ERR_OBJECT_ERROR: + result = "Error working with a graphical object"; + break; + + // + case ERR_OBJECT_NOT_FOUND: + result = "Graphical object was not found"; + break; + + // + case ERR_OBJECT_WRONG_PROPERTY: + result = "Wrong ID of a graphical object property"; + break; + + // + case ERR_OBJECT_GETDATE_FAILED: + result = "Unable to get date corresponding to the value"; + break; + + // + case ERR_OBJECT_GETVALUE_FAILED: + result = "Unable to get value corresponding to the date"; + break; + + // + //--- MarketInfo + + // + case ERR_MARKET_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_MARKET_NOT_SELECTED: + result = "Symbol is not selected in MarketWatch"; + break; + + // + case ERR_MARKET_WRONG_PROPERTY: + result = "Wrong identifier of a symbol property"; + break; + + // + case ERR_MARKET_LASTTIME_UNKNOWN: + result = "Time of the last tick is not known (no ticks)"; + break; + + // + case ERR_MARKET_SELECT_ERROR: + result = "Error adding or deleting a symbol in MarketWatch"; + break; + + // + //--- History Access + + // + case ERR_HISTORY_NOT_FOUND: + result = "Requested history not found"; + break; + + // + case ERR_HISTORY_WRONG_PROPERTY: + result = "Wrong ID of the history property"; + break; + + // + //--- Global_Variables + + // + case ERR_GLOBALVARIABLE_NOT_FOUND: + result = "Global variable of the client terminal is not found"; + break; + + // + case ERR_GLOBALVARIABLE_EXISTS: + result = "Global variable of the client terminal with the same name already exists"; + break; + + // + case ERR_MAIL_SEND_FAILED: + result = "Email sending failed"; + break; + + // + case ERR_PLAY_SOUND_FAILED: + result = "Sound playing failed"; + break; + + // + case ERR_MQL5_WRONG_PROPERTY: + result = "Wrong identifier of the program property"; + break; + + // + case ERR_TERMINAL_WRONG_PROPERTY: + result = "Wrong identifier of the terminal property"; + break; + + // + case ERR_FTP_SEND_FAILED: + result = "File sending via ftp failed"; + break; + + // + case ERR_NOTIFICATION_SEND_FAILED: + result = "Error in sending notification"; + break; + + // + //--- Custom Indicator Buffers + + // + case ERR_BUFFERS_NO_MEMORY: + result = "Not enough memory for the distribution of indicator buffers"; + break; + + // + case ERR_BUFFERS_WRONG_INDEX: + result = "Wrong indicator buffer index"; + break; + + // + //--- Custom Indicator Properties + + // + case ERR_CUSTOM_WRONG_PROPERTY: + result = "Wrong ID of the custom indicator property"; + break; + + // + //--- Account + + // + case ERR_ACCOUNT_WRONG_PROPERTY: + result = "Wrong account property ID"; + break; + + // + case ERR_TRADE_WRONG_PROPERTY: + result = "Wrong trade property ID"; + break; + + // + case ERR_TRADE_DISABLED: + result = "Trading by Expert Advisors prohibited"; + break; + + // + case ERR_TRADE_POSITION_NOT_FOUND: + result = "Position not found"; + break; + + // + case ERR_TRADE_ORDER_NOT_FOUND: + result = "Order not found"; + break; + + // + case ERR_TRADE_DEAL_NOT_FOUND: + result = "Deal not found"; + break; + + // + case ERR_TRADE_SEND_FAILED: + result = "Trade request sending failed"; + break; + + // + //--- Indicators + + // + case ERR_INDICATOR_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_INDICATOR_CANNOT_CREATE: + result = "Indicator cannot be created"; + break; + + // + case ERR_INDICATOR_NO_MEMORY: + result = "Not enough memory to add the indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_APPLY: + result = "The indicator cannot be applied to another indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_ADD: + result = "Error applying an indicator to chart"; + break; + + // + case ERR_INDICATOR_DATA_NOT_FOUND: + result = "Requested data not found"; + break; + + // + case ERR_INDICATOR_WRONG_HANDLE: + result = "Wrong indicator handle"; + break; + + // + case ERR_INDICATOR_WRONG_PARAMETERS: + result = "Wrong number of parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_PARAMETERS_MISSING: + result = "No parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_CUSTOM_NAME: + result = "The first parameter in the array must be the name of the custom indicator"; + break; + + // + case ERR_INDICATOR_PARAMETER_TYPE: + result = "Invalid parameter type in the array when creating an indicator"; + break; + + // + case ERR_INDICATOR_WRONG_INDEX: + result = "Wrong index of the requested indicator buffer"; + break; + + // + //--- Depth of Market + + // + case ERR_BOOKS_CANNOT_ADD: + result = "Depth Of Market can not be added"; + break; + + // + case ERR_BOOKS_CANNOT_DELETE: + result = "Depth Of Market can not be removed"; + break; + + // + case ERR_BOOKS_CANNOT_GET: + result = "The data from Depth Of Market can not be obtained"; + break; + + // + case ERR_BOOKS_CANNOT_SUBSCRIBE: + result = "Error in subscribing to receive new data from Depth Of Market"; + break; + + // + //--- File Operations + + // + case ERR_TOO_MANY_FILES: + result = "More than 64 files cannot be opened at the same time"; + break; + + // + case ERR_WRONG_FILENAME: + result = "Invalid file name"; + break; + + // + case ERR_TOO_LONG_FILENAME: + result = "Too long file name"; + break; + + // + case ERR_CANNOT_OPEN_FILE: + result = "File opening error"; + break; + + // + case ERR_FILE_CACHEBUFFER_ERROR: + result = "Not enough memory for cache to read"; + break; + + // + case ERR_CANNOT_DELETE_FILE: + result = "File deleting error"; + break; + + // + case ERR_INVALID_FILEHANDLE: + result = "A file with this handle was closed, or was not opening at all"; + break; + + // + case ERR_WRONG_FILEHANDLE: + result = "Wrong file handle"; + break; + + // + case ERR_FILE_NOTTOWRITE: + result = "The file must be opened for writing"; + break; + + // + case ERR_FILE_NOTTOREAD: + result = "The file must be opened for reading"; + break; + + // + case ERR_FILE_NOTBIN: + result = "The file must be opened as a binary one"; + break; + + // + case ERR_FILE_NOTTXT: + result = "The file must be opened as a text"; + break; + + // + case ERR_FILE_NOTTXTORCSV: + result = "The file must be opened as a text or CSV"; + break; + + // + case ERR_FILE_NOTCSV: + result = "The file must be opened as CSV"; + break; + + // + case ERR_FILE_READERROR: + result = "File reading error"; + break; + + // + case ERR_FILE_BINSTRINGSIZE: + result = "String size must be specified, because the file is opened as binary"; + break; + + // + case ERR_INCOMPATIBLE_FILE: + result = "A text file must be for string arrays, for other arrays - binary"; + break; + + // + case ERR_FILE_IS_DIRECTORY: + result = "This is not a file, this is a directory"; + break; + + // + case ERR_FILE_NOT_EXIST: + result = "File does not exist"; + break; + + // + case ERR_FILE_CANNOT_REWRITE: + result = "File can not be rewritten"; + break; + + // + case ERR_WRONG_DIRECTORYNAME: + result = "Wrong directory name"; + break; + + // + case ERR_DIRECTORY_NOT_EXIST: + result = "Directory does not exist"; + break; + + // + case ERR_FILE_ISNOT_DIRECTORY: + result = "This is a file, not a directory"; + break; + + // + case ERR_CANNOT_DELETE_DIRECTORY: + result = "The directory cannot be removed"; + break; + + // + case ERR_CANNOT_CLEAN_DIRECTORY: + result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)"; + break; + + // + case ERR_FILE_WRITEERROR: + result = "Failed to write a resource to a file"; + break; + + // + //--- String Casting + + // + case ERR_NO_STRING_DATE: + result = "No date in the string"; + break; + + // + case ERR_WRONG_STRING_DATE: + result = "Wrong date in the string"; + break; + + // + case ERR_WRONG_STRING_TIME: + result = "Wrong time in the string"; + break; + + // + case ERR_STRING_TIME_ERROR: + result = "Error converting string to date"; + break; + + // + case ERR_STRING_OUT_OF_MEMORY: + result = "Not enough memory for the string"; + break; + + // + case ERR_STRING_SMALL_LEN: + result = "The string length is less than expected"; + break; + + // + case ERR_STRING_TOO_BIGNUMBER: + result = "Too large number, more than ULONG_MAX"; + break; + + // + case ERR_WRONG_FORMATSTRING: + result = "Invalid format string"; + break; + + // + case ERR_TOO_MANY_FORMATTERS: + result = "Amount of format specifiers more than the parameters"; + break; + + // + case ERR_TOO_MANY_PARAMETERS: + result = "Amount of parameters more than the format specifiers"; + break; + + // + case ERR_WRONG_STRING_PARAMETER: + result = "Damaged parameter of string type"; + break; + + // + case ERR_STRINGPOS_OUTOFRANGE: + result = "Position outside the string"; + break; + + // + case ERR_STRING_ZEROADDED: + result = "0 added to the string end, a useless operation"; + break; + + // + case ERR_STRING_UNKNOWNTYPE: + result = "Unknown data type when converting to a string"; + break; + + // + case ERR_WRONG_STRING_OBJECT: + result = "Damaged string object"; + break; + + // + //--- Operations with Arrays + + // + case ERR_INCOMPATIBLE_ARRAYS: + result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"; + break; + + // + case ERR_SMALL_ASSERIES_ARRAY: + result = "The receiving array is declared as AS_SERIES, and it is of insufficient size"; + break; + + // + case ERR_SMALL_ARRAY: + result = "Too small array, the starting position is outside the array"; + break; + + // + case ERR_ZEROSIZE_ARRAY: + result = "An array of zero length"; + break; + + // + case ERR_NUMBER_ARRAYS_ONLY: + result = "Must be a numeric array"; + break; + + // + case ERR_ONEDIM_ARRAYS_ONLY: + result = "Must be a one-dimensional array"; + break; + + // + case ERR_SERIES_ARRAY: + result = "Timeseries cannot be used"; + break; + + // + case ERR_DOUBLE_ARRAY_ONLY: + result = "Must be an array of type double"; + break; + + // + case ERR_FLOAT_ARRAY_ONLY: + result = "Must be an array of type float"; + break; + + // + case ERR_LONG_ARRAY_ONLY: + result = "Must be an array of type long"; + break; + + // + case ERR_INT_ARRAY_ONLY: + result = "Must be an array of type int"; + break; + + // + case ERR_SHORT_ARRAY_ONLY: + result = "Must be an array of type short"; + break; + + // + case ERR_CHAR_ARRAY_ONLY: + result = "Must be an array of type char"; + break; + + // + //--- Operations with OpenCL + + // + case ERR_OPENCL_NOT_SUPPORTED: + result = "OpenCL functions are not supported on this computer"; + break; + + // + case ERR_OPENCL_INTERNAL: + result = "Internal error occurred when running OpenCL"; + break; + + // + case ERR_OPENCL_INVALID_HANDLE: + result = "Invalid OpenCL handle"; + break; + + // + case ERR_OPENCL_CONTEXT_CREATE: + result = "Error creating the OpenCL context"; + break; + + // + case ERR_OPENCL_QUEUE_CREATE: + result = "Failed to create a run queue in OpenCL"; + break; + + // + case ERR_OPENCL_PROGRAM_CREATE: + result = "Error occurred when compiling an OpenCL program"; + break; + + // + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: + result = "Too long kernel name (OpenCL kernel)"; + break; + + // + case ERR_OPENCL_KERNEL_CREATE: + result = "Error creating an OpenCL kernel"; + break; + + // + case ERR_OPENCL_SET_KERNEL_PARAMETER: + result = "Error occurred when setting parameters for the OpenCL kernel"; + break; + + // + case ERR_OPENCL_EXECUTE: + result = "OpenCL program runtime error"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_SIZE: + result = "Invalid size of the OpenCL buffer"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_OFFSET: + result = "Invalid offset in the OpenCL buffer"; + break; + + // + case ERR_OPENCL_BUFFER_CREATE: + result = "Failed to create and OpenCL buffer"; + break; + + // + //--- User-Defined Errors + default: + result = "UNKNOWN Erro ..."; + break; + } + + // + return result; + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + // + string result = ""; + + // + switch (return_code) + { + // + case TRADE_RETCODE_REQUOTE: + result = "Requote"; + break; + + // + case TRADE_RETCODE_REJECT: + result = "Request rejected"; + break; + + // + case TRADE_RETCODE_CANCEL: + result = "Request canceled by trader"; + break; + + // + case TRADE_RETCODE_PLACED: + result = "Order placed"; + break; + + // + case TRADE_RETCODE_DONE: + result = "Request completed"; + break; + + // + case TRADE_RETCODE_DONE_PARTIAL: + result = "Only part of the request was completed"; + break; + + // + case TRADE_RETCODE_ERROR: + result = "Request processing error"; + break; + + // + case TRADE_RETCODE_TIMEOUT: + result = "Request canceled by timeout"; + break; + + // + case TRADE_RETCODE_INVALID: + result = "Invalid request"; + break; + + // + case TRADE_RETCODE_INVALID_VOLUME: + result = "Invalid volume in the request"; + break; + + // + case TRADE_RETCODE_INVALID_PRICE: + result = "Invalid price in the request"; + break; + + // + case TRADE_RETCODE_INVALID_STOPS: + result = "Invalid stops in the request"; + break; + + // + case TRADE_RETCODE_TRADE_DISABLED: + result = "Trade is disabled"; + break; + + // + case TRADE_RETCODE_MARKET_CLOSED: + result = "Market is closed"; + break; + + // + case TRADE_RETCODE_NO_MONEY: + result = "There is not enough money to complete the request"; + break; + + // + case TRADE_RETCODE_PRICE_CHANGED: + result = "Prices changed"; + break; + + // + case TRADE_RETCODE_PRICE_OFF: + result = "There are no quotes to process the request"; + break; + + // + case TRADE_RETCODE_INVALID_EXPIRATION: + result = "Invalid order expiration date in the request"; + break; + + // + case TRADE_RETCODE_ORDER_CHANGED: + result = "Order state changed"; + break; + + // + case TRADE_RETCODE_TOO_MANY_REQUESTS: + result = "Too frequent requests"; + break; + + // + case TRADE_RETCODE_NO_CHANGES: + result = "No changes in request"; + break; + + // + case TRADE_RETCODE_SERVER_DISABLES_AT: + result = "Autotrading disabled by server"; + break; + + // + case TRADE_RETCODE_CLIENT_DISABLES_AT: + result = "Autotrading disabled by client terminal"; + break; + + // + case TRADE_RETCODE_LOCKED: + result = "Request locked for processing"; + break; + + // + case TRADE_RETCODE_FROZEN: + result = "Order or position frozen"; + break; + + // + case TRADE_RETCODE_INVALID_FILL: + result = "Invalid order filling type"; + break; + + // + case TRADE_RETCODE_CONNECTION: + result = "No connection with the trade server"; + break; + + // + case TRADE_RETCODE_ONLY_REAL: + result = "Operation is allowed only for live accounts"; + break; + + // + case TRADE_RETCODE_LIMIT_ORDERS: + result = "The number of pending orders has reached the limit"; + break; + + // + case TRADE_RETCODE_LIMIT_VOLUME: + result = "The volume of orders and positions for the symbol has reached the limit"; + break; + + // + default: + result = "Invalid return code of the trade server"; + break; + } + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + + // + bool CanLog() + { + return mLogAlerts; + } + + // + bool CanLogAlert() + { + // + bool result = GetEnableAlerts() && GetLogAlerts(); + + // + return result; + } + + // + bool CanTerminalAlert() + { + // + bool result = GetEnableAlerts() && GetTerminalAlerts(); + + // + return result; + } + + // + bool CanMailAlert() + { + // + bool result = GetEnableAlerts() && GetMailAlerts(); + + // + return result; + } + + // + bool CanPushAlert() + { + // + bool result = GetEnableAlerts() && GetPushAlerts(); + + // + return result; + } + + // + void Save(string message) + { + // + if (!mSaveAlerts || + !IsValid(message) || + message == mLastSavedMessage || + PrepareMessage(message) == mLastSavedMessage) + { + return; + } + + // + string filePath = collector.GetFilePath("XLogs"); + if (!IsValid(filePath)) + { + return; + } + + // + // Attach Time ... + string savedMessage = ToXString(TimeCurrent()) + " " + message; + + // + bool has = collector.Append( + filePath, + savedMessage // + ); + if (has) + { + mLastSavedMessage = message; + } + } + + private: + // + // Props ... + string mPrefix; // Alerts Prefixe + bool mEnableAlerts; // Enable Alerts + bool mSaveAlerts; // Save Alerts + bool mLogAlerts; // Log Alerts + bool mTerminalAlerts; // Terminal Alerts + bool mMailAlerts; // Mail Alerts + bool mPushAlerts; // Push Alerts + + // + string mLastSavedMessage; // For Prevent Multiple Saving Same Mesage ... + XCDataCollector *collector; + + // + // Tools ... + + // + // Clear Escape String and + // Attach Alert Prefix to Message ... + string PrepareMessage(string message) + { + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, GetPrefix(), " > ", message); + + // + return message; + } +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-app-dialog.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-app-dialog.class.mq5 new file mode 100644 index 0000000..fc3de5e --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-app-dialog.class.mq5 @@ -0,0 +1,278 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCPanel +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include + +// +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Extentions ... + +/** + * Check a Qery Contains in a Content or not ... + * + * @param mQuery: String ... + * @param mContent: String ... + * @param ignoreCase: Boolean ... + * + * @return ( bool ) + */ +bool XContains( + string mQuery, // Search String + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + return Contains( + mQuery, + mContent, + ignoreCase // + ); +} + +// +// Implementation ... + +// +// a Base App Dialog Class ... +class XCAppDialog : public CAppDialog +{ + public: + // + // Action ... + + // + // Virual ... + + /** + * Override Close Button Click Action ... + */ + void OnClickButtonClose() + { + // + bool isClosed = ConfirmDialog("Close EA ?"); + + // + if (isClosed) + { + Destroy(); + } + } + + // + // Configuration Actions ... + + /** + * Show or Hide Minimize Button ... + * + * @param show: boolean + */ + void MinimizeButton(bool show) + { + // + int controlIDX = ControlFind("MinMax"); + if (!IsValidIndex(controlIDX)) + { + return; + } + + // + if (show) + { + Control(controlIDX).Show(); + } + else + { + Control(controlIDX).Hide(); + } + } + + /** + * Show or Hide Close Button ... + * + * @param show: boolean + */ + void CloseButton(bool show) + { + // + int controlIDX = ControlFind("Close"); + if (!IsValidIndex(controlIDX)) + { + return; + } + + // + if (show) + { + Control(controlIDX).Show(); + } + else + { + Control(controlIDX).Hide(); + } + } + + /** + * Minimize Functionality Implementation ... + */ + void Minimize() + { + // + m_minimized = true; + Rebound(m_min_rect); + ClientAreaVisible(false); + } + + /** + * Set Background Color ... + * + * @param clr: Color ... + */ + void BackgroundColor(color clr) + { + // + int controlIDX = ControlFind("Client"); + if (!IsValidIndex(controlIDX)) + { + return; + } + + // + CWnd *obj = Control(controlIDX); + CWndClient *wndclient = (CWndClient *)obj; + + // + wndclient.ColorBackground(clr); + } + + // + // Overrides ... + + // + protected: + // + + /** + * Find Specific Control in Dialog ... + * + * @param name: String to Search + * + * @return ( int ) + */ + int ControlFind(string name) + { + // + int result = -1; + + // + if (!IsValid(name)) + { + return result; + } + + // + int count = ControlsTotal(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + string iName = Control(i).Name(); + + // + bool isContains = XContains( + name, + iName, + true // Ignore Case ... + ); + if (isContains) + { + // + result = i; + break; + } + } + + // + return result; + } + + /** + * Create and Run Confirm Dialog ... + * + * @param message: message for Message Box ... + * + * @return ( bool ) + */ + bool ConfirmDialog(string message = NULL) + { + // + bool result = false; + + // + if (!IsValid(message)) + { + message = "Confirm ?"; + } + + // + int dialogResult = MessageBox(message, NULL, MB_YESNO); + + // + // use 'switch' or 'if' as needed + switch (dialogResult) + { + // + // Yes ... + case IDYES: + result = true; + break; + // + // No ... + case IDNO: + result = false; + break; + // + // Cancel ... + case IDCANCEL: + result = false; + break; + } + + // + return result; + } + + // + private: + // + + // +}; \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-backtester.expert.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-backtester.expert.class.mq5 new file mode 100644 index 0000000..eb1fbb8 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-backtester.expert.class.mq5 @@ -0,0 +1,2373 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCBackTesterEA +// Description: Back Tester Expert Class ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-chart.helper.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" + +// +// Import Chart Objects ... +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Definitions ... + +// +// Implementation ... +class XCBackTesterEA : public XCBase +{ + // + // Public ... + public: + // + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Symbol / Period ... + string symbol; // Symbol + ENUM_TIMEFRAMES period; // Period + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // SL/TP Manipulation Props ... + double allowedTPSLStep; // Value for Change TP/SL in Each Step ... + double minAllowedRiskInPoint; // Min Allowed Risk in Point ... + double riskInPoint; // Risk in Point per Trades ... + double riskToRewardRatio; // Risk To Reward per Trades ... + double volume; // Default volume Per Trade ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCTrade *eaTrader; // EA Scope Trade Handler ... + XCChartHelper *eaChartHelper; // Chart Helper Class ... + + // + // Constructor ... + XCBackTesterEA() + { + // + selectedPositionID = 0; + + // + volume = 0.01; + riskInPoint = 50; + allowedTPSLStep = 5; + riskToRewardRatio = 2; + minAllowedRiskInPoint = 10; + } + + // + // Deconstructor ... + ~XCBackTesterEA() + { + } + + // + // Actions / Handlers ... + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Trader ... + eaTrader = new XCTrade( + eaSlippage, + eaMagicNumber, + 0, + 0, + 0 // + ); + + // + // Trade Handler Attachments ... + + // + // Position Modifiy Event Handlers ... + count = ArraySize(mOnModifyEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); + } + } + + // + // Position Stop Loss Event Handlers ... + count = ArraySize(mStopLossEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); + } + } + + // + // Position Take Profit Event Handlers ... + count = ArraySize(mTakeProfitEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); + } + } + + // + // Position Force Close Event Handlers ... + count = ArraySize(mOnForceCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); + } + } + + // + // Deals Changed Event Handlers ... + count = ArraySize(mDealsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); + } + } + + // + // Orders Changed Event Handlers ... + count = ArraySize(mOrdersChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); + } + } + + // + // Positions Changed Event Handlers ... + count = ArraySize(mPositionsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); + } + } + + // + // Trade Changed Event Handlers ... + count = ArraySize(mTradeStateChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); + } + } + + // + // Postion Partially Close Event Handlers ... + count = ArraySize(mOnPartialCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); + } + } + + // + // Initial GUI ... + result = InitGUI(); + if (!result) + { + return result; + } + + // + // Normalize Requirements ... + NormalizeProps(); + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + delete eaTrader; + ZeroMemory(eaTrader); + + // + SpecifiedClean(mOnModifyEventHandlers); + SpecifiedClean(mStopLossEventHandlers); + SpecifiedClean(mTakeProfitEventHandlers); + SpecifiedClean(mOnForceCloseEventHandlers); + SpecifiedClean(mDealsChangedEventHandlers); + SpecifiedClean(mOrdersChangedEventHandlers); + SpecifiedClean(mOnPartialCloseEventHandlers); + SpecifiedClean(mPositionsChangedEventHandlers); + SpecifiedClean(mTradeStateChangedEventHandlers); + + // + DestroyGUI(); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + UpdateGUI(); + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + eaTrader.HandleOnTrade(); + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // TODO: Handle this ... + result = true; + + // + return result; + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + // + // Update Position Buttons ... + UpdatePositionButtons(); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + // + // Update Position Buttons ... + UpdatePositionButtons(); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + // + // Update Position Buttons ... + UpdatePositionButtons(); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + // + // Update Position Buttons ... + UpdatePositionButtons(); + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // Props and Setter / Getter (s) ... + + // + // Trade Event Listeners ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers // + ); + } + + // + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers // + ); + } + + // + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers // + ); + } + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers // + ); + } + + // + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers // + ); + } + + // + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + // Trade Event Listeners ... + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + // Object Props ... + + // + string objSuffix; + + // + CButton btnBuy; + CButton btnSell; + CButton btnClose; + CButton btnCloseAll; + CEdit lblPositionId; + + // + CButton lblTP; + CButton lblSL; + CButton btnSLPlus; + CButton btnTPPlus; + CButton btnSLMinus; + CButton btnTPMinus; + CButton btnSLPlusPlus; + CButton btnTPPlusPlus; + CButton btnSLMinusMinus; + CButton btnTPMinusMinus; + + // + CArrayObj posArray; + CButton *btnSelectedPosInfo; + CArrayObj selectedPosInfoArr; + + // + ulong selectedPositionID; + bool showSelectedPositionInfo; + + // + // GUI Event(s) ... + + /** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ + bool InitGUI() + { + // + bool result = false; + + // + int subWindow = 0; + ulong chartId = ChartID(); + objSuffix = eaLogSuffix + "_"; + + // + // Initial Chart Class Instance ... + eaChartHelper = new XCChartHelper(chartId); + + // + int startX = 5; + int startY = 25; + + // + int defaultGap = 5; + int defaultWidth = 100; + int defaultHeight = 30; + + // + // Buy ... + int btnBuyX1 = startX; + int btnBuyX2 = startX + defaultWidth; + int btnBuyY1 = startY; + int btnBuyY2 = startY + defaultHeight; + string btnBuyName = objSuffix + "BTN_BUY"; + result = btnBuy.Create( + chartId, + btnBuyName, + subWindow, + btnBuyX1, + btnBuyY1, + btnBuyX2, + btnBuyY2 // + ); + if (result) + { + // + // Apply Buy Button Style ... + + // + btnBuy.Text("Buy"); + btnBuy.Color(clrYellow); + btnBuy.ColorBackground(clrGreen); + } + + // + // Sell ... + int btnSellX1 = btnBuyX1 + btnBuyX2; + int btnSellX2 = btnSellX1 + defaultWidth; + int btnSellY1 = btnBuyY1; + int btnSellY2 = btnBuyY2; + string btnSellName = objSuffix + "BTN_SELL"; + result = btnSell.Create( + chartId, + btnSellName, + subWindow, + btnSellX1, + btnSellY1, + btnSellX2, + btnSellY2 // + ); + if (result) + { + // + // Apply Sell Button Style ... + + // + btnSell.Text("Sell"); + btnSell.Color(clrYellow); + btnSell.ColorBackground(clrDarkRed); + } + + // + // LABEL Position ID ... + int lblPositionIdX1 = btnBuyX1; + int lblPositionIdX2 = lblPositionIdX1 + defaultWidth; + int lblPositionIdY1 = btnSellY2 + defaultGap; + int lblPositionIdY2 = lblPositionIdY1 + defaultHeight; + string lblPositionIdName = objSuffix + "LBL_POS_ID"; + result = lblPositionId.Create( + chartId, + lblPositionIdName, + subWindow, + lblPositionIdX1, + lblPositionIdY1, + lblPositionIdX2, + lblPositionIdY2 // + ); + if (result) + { + // + // Apply Label Position ID Style ... + lblPositionId.ReadOnly(true); + lblPositionId.Text("Pos ID: "); + lblPositionId.Color(clrYellow); + lblPositionId.ColorBackground(clrDarkGray); + } + + // + // Close ... + int btnCloseX1 = startX; + int btnCloseX2 = btnCloseX1 + defaultWidth; + int btnCloseY1 = lblPositionIdY2 + defaultGap; + int btnCloseY2 = btnCloseY1 + defaultHeight; + string btnCloseName = objSuffix + "BTN_CLOSE"; + result = btnClose.Create( + chartId, + btnCloseName, + subWindow, + btnCloseX1, + btnCloseY1, + btnCloseX2, + btnCloseY2 // + ); + if (result) + { + // + // Apply Close Button Style ... + + // + btnClose.Text("Close"); + btnClose.Color(clrYellow); + btnClose.ColorBackground(clrDarkOrange); + } + + // + // Close All ... + int btnCloseAllX1 = btnCloseX2 + defaultGap; + int btnCloseAllX2 = btnCloseAllX1 + defaultWidth; + int btnCloseAllY1 = lblPositionIdY2 + defaultGap; + int btnCloseAllY2 = btnCloseAllY1 + defaultHeight; + string btnCloseAllName = objSuffix + "BTN_CLOSE_ALL"; + result = btnCloseAll.Create( + chartId, + btnCloseAllName, + subWindow, + btnCloseAllX1, + btnCloseAllY1, + btnCloseAllX2, + btnCloseAllY2 // + ); + if (result) + { + // + // Apply Close Button Style ... + + // + btnCloseAll.Text("Close All"); + btnCloseAll.Color(clrYellow); + btnCloseAll.ColorBackground(clrDarkRed); + } + + // + int minusPlusWidth = 20; + + // + // TP Label ... + int lblTPX1 = btnCloseX1; + int lblTPX2 = lblTPX1 + defaultWidth; + int lblTPY1 = btnCloseY2 + defaultGap; + int lblTPY2 = lblTPY1 + defaultHeight; + string lblTPName = objSuffix + "LBL_TP"; + result = lblTP.Create( + chartId, + lblTPName, + subWindow, + lblTPX1, + lblTPY1, + lblTPX2, + lblTPY2 // + ); + if (result) + { + // + // Apply Style ... + lblTP.Disable(); + lblTP.Text("TP"); + lblTP.Color(clrWhite); + lblTP.ColorBackground(clrGreen); + } + + // + // TP Plus ... + int btnTPPlusX1 = lblTPX1; + int btnTPPlusX2 = btnTPPlusX1 + minusPlusWidth; + int btnTPPlusY1 = lblTPY2 + defaultGap; + int btnTPPlusY2 = btnTPPlusY1 + defaultHeight; + string btnTPPlusName = objSuffix + "BTN_TP_PLUS"; + result = btnTPPlus.Create( + chartId, + btnTPPlusName, + subWindow, + btnTPPlusX1, + btnTPPlusY1, + btnTPPlusX2, + btnTPPlusY2 // + ); + if (result) + { + // + // Apply Style ... + btnTPPlus.Text("+"); + btnTPPlus.Color(clrYellow); + btnTPPlus.ColorBackground(clrGreen); + } + + // + // TP Plus Plus ... + int btnTPPlusPlusX1 = btnTPPlusX2 + defaultGap; + int btnTPPlusPlusX2 = btnTPPlusPlusX1 + minusPlusWidth; + int btnTPPlusPlusY1 = lblTPY2 + defaultGap; + int btnTPPlusPlusY2 = btnTPPlusPlusY1 + defaultHeight; + string btnTPPlusPlusName = objSuffix + "BTN_TP_PLUSPLUS"; + result = btnTPPlusPlus.Create( + chartId, + btnTPPlusPlusName, + subWindow, + btnTPPlusPlusX1, + btnTPPlusPlusY1, + btnTPPlusPlusX2, + btnTPPlusPlusY2 // + ); + if (result) + { + // + // Apply Style ... + btnTPPlusPlus.Text("++"); + btnTPPlusPlus.Color(clrYellow); + btnTPPlusPlus.ColorBackground(clrGreen); + } + + // + // TP Minus ... + int btnTPMinusX1 = lblTPX2 - minusPlusWidth; + int btnTPMinusX2 = btnTPMinusX1 + minusPlusWidth; + int btnTPMinusY1 = lblTPY2 + defaultGap; + int btnTPMinusY2 = btnTPMinusY1 + defaultHeight; + string btnTPMinusName = objSuffix + "BTN_TP_MINUS"; + result = btnTPMinus.Create( + chartId, + btnTPMinusName, + subWindow, + btnTPMinusX1, + btnTPMinusY1, + btnTPMinusX2, + btnTPMinusY2 // + ); + if (result) + { + // + // Apply Style ... + btnTPMinus.Text("-"); + btnTPMinus.Color(clrYellow); + btnTPMinus.ColorBackground(clrDarkRed); + } + + // + // TP Minus Minus ... + int btnTPMinusMinusX1 = btnTPMinusX1 - minusPlusWidth - defaultGap; + int btnTPMinusMinusX2 = btnTPMinusMinusX1 + minusPlusWidth; + int btnTPMinusMinusY1 = lblTPY2 + defaultGap; + int btnTPMinusMinusY2 = btnTPMinusY1 + defaultHeight; + string btnTPMinusMinusName = objSuffix + "BTN_TP_MINUSMINUS"; + result = btnTPMinusMinus.Create( + chartId, + btnTPMinusMinusName, + subWindow, + btnTPMinusMinusX1, + btnTPMinusMinusY1, + btnTPMinusMinusX2, + btnTPMinusMinusY2 // + ); + if (result) + { + // + // Apply Style ... + btnTPMinusMinus.Text("--"); + btnTPMinusMinus.Color(clrYellow); + btnTPMinusMinus.ColorBackground(clrDarkRed); + } + + // + // SL Label ... + int lblSLX1 = btnCloseAllX1; + int lblSLX2 = lblSLX1 + defaultWidth; + int lblSLY1 = btnCloseAllY2 + defaultGap; + int lblSLY2 = lblTPY1 + defaultHeight; + string lblSLName = objSuffix + "LBL_SL"; + result = lblSL.Create( + chartId, + lblSLName, + subWindow, + lblSLX1, + lblSLY1, + lblSLX2, + lblSLY2 // + ); + if (result) + { + // + // Apply Style ... + lblSL.Disable(); + lblSL.Text("SL"); + lblSL.Color(clrWhite); + lblSL.ColorBackground(clrDarkRed); + } + + // + // SL Plus ... + int btnSLPlusX1 = lblSLX1; + int btnSLPlusX2 = btnSLPlusX1 + minusPlusWidth; + int btnSLPlusY1 = lblSLY2 + defaultGap; + int btnSLPlusY2 = btnSLPlusY1 + defaultHeight; + string btnSLPlusName = objSuffix + "BTN_SL_PLUS"; + result = btnSLPlus.Create( + chartId, + btnSLPlusName, + subWindow, + btnSLPlusX1, + btnSLPlusY1, + btnSLPlusX2, + btnSLPlusY2 // + ); + if (result) + { + // + // Apply Style ... + btnSLPlus.Text("+"); + btnSLPlus.Color(clrYellow); + btnSLPlus.ColorBackground(clrGreen); + } + + // + // SL Plus Plus ... + int btnSLPlusPlusX1 = btnSLPlusX2 + defaultGap; + int btnSLPlusPlusX2 = btnSLPlusPlusX1 + minusPlusWidth; + int btnSLPlusPlusY1 = lblSLY2 + defaultGap; + int btnSLPlusPlusY2 = btnSLPlusPlusY1 + defaultHeight; + string btnSLPlusPlusName = objSuffix + "BTN_SL_PLUSPLUS"; + result = btnSLPlusPlus.Create( + chartId, + btnSLPlusPlusName, + subWindow, + btnSLPlusPlusX1, + btnSLPlusPlusY1, + btnSLPlusPlusX2, + btnSLPlusPlusY2 // + ); + if (result) + { + // + // Apply Style ... + btnSLPlusPlus.Text("++"); + btnSLPlusPlus.Color(clrYellow); + btnSLPlusPlus.ColorBackground(clrGreen); + } + + // + // SL Minus ... + int btnSLMinusX1 = lblSLX2 - minusPlusWidth; + int btnSLMinusX2 = btnSLMinusX1 + minusPlusWidth; + int btnSLMinusY1 = lblSLY2 + defaultGap; + int btnSLMinusY2 = btnSLMinusY1 + defaultHeight; + string btnSLMinusName = objSuffix + "BTN_SL_MINUS"; + result = btnSLMinus.Create( + chartId, + btnSLMinusName, + subWindow, + btnSLMinusX1, + btnSLMinusY1, + btnSLMinusX2, + btnSLMinusY2 // + ); + if (result) + { + // + // Apply Style ... + btnSLMinus.Text("-"); + btnSLMinus.Color(clrYellow); + btnSLMinus.ColorBackground(clrDarkRed); + } + + // + // SL Minus Minus ... + int btnSLMinusMinusX1 = btnSLMinusX1 - minusPlusWidth - defaultGap; + int btnSLMinusMinusX2 = btnSLMinusMinusX1 + minusPlusWidth; + int btnSLMinusMinusY1 = lblSLY2 + defaultGap; + int btnSLMinusMinusY2 = btnSLMinusY1 + defaultHeight; + string btnSLMinusMinusName = objSuffix + "BTN_SL_MINUSMINUS"; + result = btnSLMinusMinus.Create( + chartId, + btnSLMinusMinusName, + subWindow, + btnSLMinusMinusX1, + btnSLMinusMinusY1, + btnSLMinusMinusX2, + btnSLMinusMinusY2 // + ); + if (result) + { + // + // Apply Style ... + btnSLMinusMinus.Text("--"); + btnSLMinusMinus.Color(clrYellow); + btnSLMinusMinus.ColorBackground(clrDarkRed); + } + + // + UpdateGUIState(); + + // + return result; + } + + /** + * Update GUI based on Each Ticks ... + */ + void UpdateGUI() + { + // + UpdateGUIState(); + + // + // Buy Button Pressed ... + if (btnBuy.Pressed()) + { + // + HandleBuyTrade(); + btnBuy.Pressed(false); + } + + // + // Sell Button Pressed ... + if (btnSell.Pressed()) + { + // + HandleSellTrade(); + btnSell.Pressed(false); + } + + // + // Close Button Pressed ... + if (btnClose.Pressed()) + { + // + if (btnClose.IsEnabled()) + { + // + if (selectedPositionID > 0) + { + HandleCloseTrade(selectedPositionID); + } + } + + // + btnClose.Pressed(false); + } + + // + // Close All Button Pressed ... + if (btnCloseAll.Pressed()) + { + // + if (btnCloseAll.IsEnabled()) + { + HandleCloseTrade(0); + } + + // + btnCloseAll.Pressed(false); + } + + // + // Check Show Hide Selected Position Info ... + if (btnSelectedPosInfo != NULL) + { + // + if (btnSelectedPosInfo.Pressed()) + { + // + // Check Enable ... + if (btnSelectedPosInfo.IsEnabled()) + { + // + // Handle Toggle Show/Hide lblSelectedPositionInfo ... + CEdit *iLbl = NULL; + bool isVisible = showSelectedPositionInfo; + int count = selectedPosInfoArr.Total(); + if (IsValidSize(count)) + { + // + // Loop Through Labels ... + for (int i = 0; i < count; i++) + { + // + iLbl = (CEdit *)selectedPosInfoArr.At(i); + isVisible = iLbl.IsVisible(); + if (isVisible) + { + iLbl.Hide(); + } + else + { + iLbl.Show(); + } + } + + // + // Update Button Text ... + isVisible = showSelectedPositionInfo; + string btnText = isVisible + ? "Hide Info" + : "Show Info"; + btnSelectedPosInfo.Text(btnText); + showSelectedPositionInfo = !showSelectedPositionInfo; + } + + // + ZeroMemory(iLbl); + } + + // + btnSelectedPosInfo.Pressed(false); + } + } + + // + // TP Managing ... + + // + // TP Plus ... + if (btnTPPlus.Pressed()) + { + // + if (btnTPPlus.IsEnabled()) + { + HandleTPChange(X_DIRECTION_BULLISH); + } + + // + btnTPPlus.Pressed(false); + } + + // + // TP Plus Plus ... + if (btnTPPlusPlus.Pressed()) + { + // + if (btnTPPlusPlus.IsEnabled()) + { + HandleTPChange(X_DIRECTION_BULLISH, 2); + } + + // + btnTPPlusPlus.Pressed(false); + } + + // + // TP Minus ... + if (btnTPMinus.Pressed()) + { + // + if (btnTPMinus.IsEnabled()) + { + HandleTPChange(X_DIRECTION_BEARISH); + } + + // + btnTPMinus.Pressed(false); + } + + // + // TP Minus Minus ... + if (btnTPMinusMinus.Pressed()) + { + // + if (btnTPMinusMinus.IsEnabled()) + { + HandleTPChange(X_DIRECTION_BEARISH, 2); + } + + // + btnTPMinusMinus.Pressed(false); + } + + // + // SL Managing ... + + // + // SL Plus ... + if (btnSLPlus.Pressed()) + { + // + if (btnSLPlus.IsEnabled()) + { + HandleSLChange(X_DIRECTION_BULLISH); + } + + // + btnSLPlus.Pressed(false); + } + + // + // SL Plus Plus ... + if (btnSLPlusPlus.Pressed()) + { + // + if (btnSLPlusPlus.IsEnabled()) + { + HandleSLChange(X_DIRECTION_BULLISH, 2); + } + + // + btnSLPlusPlus.Pressed(false); + } + + // + // SL Minus ... + if (btnSLMinus.Pressed()) + { + // + if (btnSLMinus.IsEnabled()) + { + HandleSLChange(X_DIRECTION_BEARISH); + } + + // + btnSLMinus.Pressed(false); + } + + // + // SL Minus Minus ... + if (btnSLMinusMinus.Pressed()) + { + // + if (btnSLMinusMinus.IsEnabled()) + { + HandleSLChange(X_DIRECTION_BEARISH, 2); + } + + // + btnSLMinusMinus.Pressed(false); + } + + // + // Check Positions Buttons ... + int posCount = posArray.Total(); + bool has = IsValidSize(posCount); + if (has) + { + // + for (int i = 0; i < posCount; i++) + { + // + CButton *iBtn = (CButton *)posArray.At(i); + + // + if (iBtn.Pressed()) + { + // + if (iBtn.IsEnabled()) + { + // + ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); + if (posID > 0 && selectedPositionID != posID) + { + selectedPositionID = posID; + UpdateGUIState(); + } + } + + // + iBtn.Pressed(false); + } + + // + ZeroMemory(iBtn); + } + } + } + + /** + * Destroy all Initialized GUi Requirements ... + */ + void DestroyGUI() + { + // + delete eaChartHelper; + ZeroMemory(eaChartHelper); + + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + + /** + * Update GUI Element Styles ... + */ + void UpdateGUIState() + { + // + // Update States Of Position Select Buttons ... + int count = posArray.Total(); + bool has = IsValidSize(count) && selectedPositionID > 0; + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + CButton *iBtn = (CButton *)posArray.At(i); + + // + ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); + + // + // Select Position ... + XPosition iPos; + bool hasPosition = eaTrader.GetPosition( + posID, + iPos // + ); + string iTooltip = + !hasPosition + ? "" + : IsLong(iPos.type) + ? "Long" + : "Short"; + + // + if (posID == selectedPositionID) + { + // + iBtn.Disable(); + iBtn.ColorBackground(clrDarkGray); + } + else + { + // + iBtn.Enable(); + + // + color iBtnBG = IsLong(iPos.type) + ? clrGreen + : clrDarkRed; + + // + iBtn.ColorBackground(iBtnBG); + } + + // + ZeroMemory(iBtn); + } + } + + // + // Update State of Close All ... + if (has && count > 1) + { + // + btnCloseAll.Enable(); + btnCloseAll.ColorBackground(clrDarkRed); + } + else + { + // + btnCloseAll.Disable(); + btnCloseAll.ColorBackground(clrDarkGray); + } + + // + // Update Selected Position Info Button State ... + if (has) + { + // + // Reading Global Chart Info ... + int subWindow = 0; + int chartWidth = eaChartHelper.Width(); + ulong chartId = eaChartHelper.ChartId(); + + // + // Read Selected Position ... + XPosition selectedPosition; + bool hasPosition = eaTrader.GetPosition( + selectedPositionID, + selectedPosition // + ); + + // + // Read All Positions ... + double profits = 0; + XPosition positions[]; + string positionsInfo = ""; + int positionsCount = eaTrader.GetPositions(positions); + has = IsValidSize(positionsCount); + if (has) + { + // + for (int i = 0; i < positionsCount; i++) + { + profits += positions[i].profit; + } + + // + if (positionsCount > 1) + { + positionsInfo = "Positions Count: " + ToXString(positionsCount) + ", Profits: " + ToXString(profits); + } + } + + // + if (hasPosition) + { + // + // Preparing Position Info ... + string posTicket = "Ticket: " + ToXString(selectedPosition.ticket); + string posType = "Type: " + ToXString(selectedPosition.type); + string posSymbolPeriod = + "Symbol: " + selectedPosition.symbol + ", " + + "Period: " + ToXString(selectedPosition.period); + string posProfit = "Profit: " + ToXString(selectedPosition.profit); + string posRiskToRewardRatio = "RiskToReward: " + ToXString(selectedPosition.GetRiskRewardRatio()); + string accountInfo = + "Balance: " + ToXString(eaTrader.mAccount.GetBalance()) + ", " + + "Equity: " + ToXString(eaTrader.mAccount.GetEquity()); + + // + string posInfos[]; + + // + // Ticket ... + Add( + posTicket, + posInfos // + ); + + // + // Type ... + Add( + posType, + posInfos // + ); + + // + // Symbol Period ... + Add( + posSymbolPeriod, + posInfos // + ); + + // + // Profit ... + Add( + posProfit, + posInfos // + ); + + // + // Risk to Reward Ratio ... + Add( + posRiskToRewardRatio, + posInfos // + ); + + // + // Add Positions Info if Exists ... + if (IsSpecifiedValid(positionsInfo)) + { + // + Add( + positionsInfo, + posInfos // + ); + + // + // Clear Info Array ... + selectedPosInfoArr.Clear(); + } + + // + // Adding Account Info ... + Add( + accountInfo, + posInfos // + ); + + // + // Create Button If Not Exists ... + if (btnSelectedPosInfo == NULL) + { + // + btnSelectedPosInfo = new CButton(); + + // + string name = objSuffix + "BTN_TOOGLE_SPOS_INFO"; + + // + CRect iRect = btnTPPlus.Rect(); + + // + int x1 = iRect.left; + int x2 = x1 + 200 + 5; + + // + int y1 = iRect.bottom + 5; + int y2 = y1 + iRect.Height(); + + // + bool isCreated = btnSelectedPosInfo.Create( + chartId, + name, + subWindow, + x1, + y1, + x2, + y2 // + ); + if (!isCreated) + { + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + else + { + // + // Apply Styles ... + btnSelectedPosInfo.Color(clrYellow); + btnSelectedPosInfo.ColorBackground(clrDarkBlue); + } + } + + // + // Check Btn Exists ... + has = btnSelectedPosInfo != NULL; + if (has) + { + // + int posInfoCount = ArraySize(posInfos); + int lblInfoCount = selectedPosInfoArr.Total(); + has = IsValidSize(lblInfoCount) && lblInfoCount == posInfoCount; + + // + // Create info Labels ... + if (!has) + { + // + selectedPosInfoArr.Clear(); + has = IsValidSize(posInfoCount); + if (has) + { + // + // Creat Info Control ... + + // + string name = objSuffix + "LBL_SPOS_INFO"; + + // + int lblHeight = 25; + int lblWidth = 450; + + // + int startX = chartWidth - lblWidth - 5; + int sizeX = startX + lblWidth; + + // + int startY = 5; + int sizeY = startY + lblHeight; + + // + // Loop through Position Info's Array to Create Label Controls ... + for (int i = 0; i < posInfoCount; i++) + { + // + string iText = posInfos[i]; + string iTextMD5 = ToMD5(iText); + + // + string iName = name + "_" + iTextMD5; + + // + int iX1 = startX; + int iX2 = sizeX; + + // + int iY1 = startY; + int iY2 = startY + lblHeight; + + // + CEdit *iLbl = new CEdit(); + bool isCreated = iLbl.Create( + chartId, + iName, + subWindow, + iX1, + iY1, + iX2, + iY2 // + ); + if (isCreated) + { + // + iLbl.Text(iText); + iLbl.Color(clrYellow); + iLbl.ColorBorder(clrDarkSlateGray); + iLbl.ColorBackground(clrDarkSlateGray); + + // + if (showSelectedPositionInfo) + { + iLbl.Show(); + } + else + { + iLbl.Hide(); + } + + // + selectedPosInfoArr.Add(iLbl); + + // + startY = iY2; + } + } + } + } + + // + // Update Info Labels ... + lblInfoCount = selectedPosInfoArr.Total(); + has = IsValidSize(lblInfoCount); + if (has) + { + // + CEdit *iLbl = NULL; + + // + // Loop Through Infos ... + for (int i = 0; i < lblInfoCount; i++) + { + // + iLbl = (CEdit *)selectedPosInfoArr.At(i); + + // + iLbl.Text(posInfos[i]); + } + + // + bool isVisible = showSelectedPositionInfo; + string btnText = isVisible + ? "Hide Info" + : "Show Info"; + btnSelectedPosInfo.Text(btnText); + + // + ZeroMemory(iLbl); + } + } + + // + ZeroMemory(posInfos); + } + + // + SpecifiedClean(positions); + } + else + { + // + // Toggle Selected Position Btn ... + if (btnSelectedPosInfo != NULL) + { + // + btnSelectedPosInfo.Destroy(); + + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + + // + // Selected Position Lbls ... + selectedPosInfoArr.Clear(); + } + + // + // Update State of BtnClose and BtnClose All ... + if (selectedPositionID == 0) + { + // + btnClose.Disable(); + btnClose.ColorBackground(clrDarkGray); + + // + lblTP.Disable(); + lblTP.ColorBackground(clrDarkGray); + + // + btnTPPlus.Disable(); + btnTPPlus.ColorBackground(clrDarkGray); + + // + btnTPPlusPlus.Disable(); + btnTPPlusPlus.ColorBackground(clrDarkGray); + + // + btnTPMinus.Disable(); + btnTPMinus.ColorBackground(clrDarkGray); + + // + btnTPMinusMinus.Disable(); + btnTPMinusMinus.ColorBackground(clrDarkGray); + + // + lblSL.Disable(); + lblSL.ColorBackground(clrDarkGray); + + // + btnSLPlus.Disable(); + btnSLPlus.ColorBackground(clrDarkGray); + + // + btnSLPlusPlus.Disable(); + btnSLPlusPlus.ColorBackground(clrDarkGray); + + // + btnSLMinus.Disable(); + btnSLMinus.ColorBackground(clrDarkGray); + + // + btnSLMinusMinus.Disable(); + btnSLMinusMinus.ColorBackground(clrDarkGray); + } + else + { + // + btnClose.Enable(); + btnClose.ColorBackground(clrDarkOrange); + + // + lblTP.Enable(); + lblTP.ColorBackground(clrGreen); + + // + btnTPPlus.Enable(); + btnTPPlus.ColorBackground(clrGreen); + + // + btnTPPlusPlus.Enable(); + btnTPPlusPlus.ColorBackground(clrGreen); + + // + btnTPMinus.Enable(); + btnTPMinus.ColorBackground(clrDarkRed); + + // + btnTPMinusMinus.Enable(); + btnTPMinusMinus.ColorBackground(clrDarkRed); + + // + lblSL.Enable(); + lblSL.ColorBackground(clrDarkRed); + + // + btnSLPlus.Enable(); + btnSLPlus.ColorBackground(clrGreen); + + // + btnSLPlusPlus.Enable(); + btnSLPlusPlus.ColorBackground(clrGreen); + + // + btnSLMinus.Enable(); + btnSLMinus.ColorBackground(clrDarkRed); + + // + btnSLMinusMinus.Enable(); + btnSLMinusMinus.ColorBackground(clrDarkRed); + } + } + + /** + * Update Position's Selector Buttons ... + */ + void UpdatePositionButtons() + { + // + // Retrieve Positions ... + XPosition positions[]; + int count = eaTrader.GetPositions( + positions // + ); + bool has = IsValidSize(count); + if (!has) + { + // + posArray.Clear(); + selectedPositionID = 0; + UpdateGUIState(); + return; + } + + // + posArray.Clear(); + + // + // Selected Position ID ... + bool isSelectdPositionIDExists = false; + if (has && selectedPositionID > 0) + { + // + for (int i = 0; i < count; i++) + { + // + if (!isSelectdPositionIDExists && + positions[i].ticket == selectedPositionID) + { + // + isSelectdPositionIDExists = true; + break; + } + } + } + if (!isSelectdPositionIDExists || + selectedPositionID == 0) + { + // + XPosition youngest; + int youngestIDX = GetXYoungest(youngest, positions); + bool hasYoungest = IsValidIndex(youngestIDX) && + youngest.IsValid(); + if (hasYoungest) + { + selectedPositionID = youngest.ticket; + } + + // + youngest.Clean(); + } + + // + int subWindow = 0; + ulong chartId = eaChartHelper.ChartId(); + + // + int btnWidth = 25; + int btnHeight = 25; + + // + CRect iRect = lblPositionId.Rect(); + + // + int lastX = iRect.left + iRect.Width() + 5; + int lastSizeX = lastX + btnWidth; + + // + int lastY = iRect.top; + int lastSizeY = lastY + iRect.Height(); + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPos = positions[i]; + + // + string posTypeStr = IsLong(iPos.type) + ? "LONG" + : "SHORT"; + + // + int iPosBtnX = lastX; + int iPosBtnSizeX = iPosBtnX + btnWidth; + string iPosBtnName = objSuffix + "_" + posTypeStr + "_POS_SELECT_BTN_" + ToXString(iPos.ticket); + + // + CButton *iPosBtn = new CButton(); + has = iPosBtn.Create( + chartId, + iPosBtnName, + subWindow, + iPosBtnX, + lastY, + iPosBtnSizeX, + lastSizeY // + ); + if (has) + { + // + // Apply Styles ... + string iPosBtnText = ToXString(iPos.ticket); + + // + iPosBtn.Text(iPosBtnText); + iPosBtn.Color(clrWhite); + + // + color iPosBtnBG = IsLong(iPos.type) + ? clrGreen + : clrDarkRed; + iPosBtn.ColorBackground(iPosBtnBG); + + // + lastX = iPosBtnSizeX + 5; + + // + if (selectedPositionID == iPos.ticket) + { + iPosBtn.Disable(); + } + + // + posArray.Add(iPosBtn); + } + + // + iPos.Clean(); + } + + // + ZeroMemory(positions); + UpdateGUIState(); + } + + // + // GUI Event Handlers ... + + // + void HandleBuyTrade() + { + HandleTrade(X_DIRECTION_BULLISH); + } + + // + void HandleSellTrade() + { + HandleTrade(X_DIRECTION_BEARISH); + } + + // + void HandleTrade(ENUM_X_DIRECTION dir) + { + // + if (!HasDirection(dir)) + { + return; + } + + // + NormalizeProps(); + + // + bool isBullish = IsSpecifiedBullish(dir); + + // + double r2r = riskToRewardRatio; + double _volume = volume; + double _riskInPoints = riskInPoint; + double point = GetPoints(symbol); + double entry = GetEntry(symbol, dir); + + // + double risk = _riskInPoints * point; + double reward = risk * r2r; + + // + double sl = isBullish + ? entry - risk + : entry + risk; + double tp = isBullish + ? entry + reward + : entry - reward; + + // + string comment = ShortName + "_POS_" + ToXString(dir); + + // + if (isBullish) + { + // + eaTrader.Buy( + symbol, + period, + _volume, + entry, + sl, + tp, + comment // + ); + } + else + { + // + eaTrader.Sell( + symbol, + period, + _volume, + entry, + sl, + tp, + comment // + ); + } + } + + // + void HandleCloseTrade(ulong positionID) + { + // + if (positionID == 0) + { + // + XPosition positions[]; + int count = eaTrader.GetPositions( + positions // + ); + bool has = IsValidSize(count); + if (has) + { + // + int closedCount = eaTrader.Close(positions); + has = IsValidSize(closedCount); + } + } + else + { + // + XPosition position; + bool has = eaTrader.GetPosition( + positionID, + position // + ); + if (has) + { + // + has = eaTrader.Close(positionID); + } + } + } + + // + void HandleTPChange( + ENUM_X_DIRECTION dir, + int multiplier = 1 // + ) + { + // + // Validate ... + if (selectedPositionID == 0 || !HasDirection(dir)) + { + return; + } + + // + NormalizeProps(); + + // + // Normalize Multiplier ... + multiplier = NormalizeInt(multiplier, 1, 2); + + // + // Select Position ... + XPosition position; + bool has = eaTrader.GetPosition( + selectedPositionID, + position // + ); + if (!has) + { + // + position.Clean(); + return; + } + + // + bool isLong = IsLong(position.type); + bool isBullish = IsSpecifiedBullish(dir); + + // + double point = GetPoints(position.symbol); + double stepValue = multiplier * (point * allowedTPSLStep); + + // + bool mustIncrease = + isBullish + ? isLong + : !isLong; + + // + double tp = position.tp; + tp = + mustIncrease + ? tp + stepValue + : tp - stepValue; + bool isModified = eaTrader.Modify( + position.ticket, + position.sl, + tp, + objSuffix + "Change TP" // + ); + if (isModified) + { + UpdateGUIState(); + } + + // + position.Clean(); + } + + // + void HandleSLChange( + ENUM_X_DIRECTION dir, + int multiplier = 1 // + ) + { + // + // Validate ... + if (selectedPositionID == 0 || !HasDirection(dir)) + { + return; + } + + // + NormalizeProps(); + + // + // Normalize Multiplier ... + multiplier = NormalizeInt(multiplier, 1, 2); + + // + // Select Position ... + XPosition position; + bool has = eaTrader.GetPosition( + selectedPositionID, + position // + ); + if (!has) + { + // + position.Clean(); + return; + } + + // + bool isLong = IsLong(position.type); + bool isBullish = IsSpecifiedBullish(dir); + + // + double point = GetPoints(position.symbol); + double stepValue = multiplier * (point * allowedTPSLStep); + + // + bool mustIncrease = + isBullish + ? !isLong + : isLong; + + // + double risk = position.GetRiskInPoint(); + if (risk <= minAllowedRiskInPoint) + { + // + position.Clean(); + return; + } + + // + double sl = position.sl; + sl = + mustIncrease + ? sl + stepValue + : sl - stepValue; + bool isModified = eaTrader.Modify( + position.ticket, + sl, + position.tp, + objSuffix + "Change SL" // + ); + if (isModified) + { + UpdateGUIState(); + } + + // + position.Clean(); + } + + // + // Custom Tools ... + + // + void NormalizeProps() + { + // + if (volume < 0.01) + { + volume = 0.01; + } + + // + if (riskInPoint < 0) + { + riskInPoint = 50; + } + + // + if (allowedTPSLStep < 5) + { + allowedTPSLStep = 5; + } + + // + if (riskToRewardRatio < 0.5) + { + riskToRewardRatio = 2; + } + + // + if (minAllowedRiskInPoint < 10) + { + minAllowedRiskInPoint = 10; + } + } + + // + ulong ExtractPositionIDFromButtonName(string name) + { + // + ulong result = 0; + + // + string nameParts[]; + int namePartsCount = SplitContent(nameParts, name, "_"); + bool has = IsValidSize(namePartsCount); + if (has) + { + // + string lastPart = nameParts[namePartsCount - 1]; + StringReplace(lastPart, "_", ""); + result = (long)lastPart; + } + + // + ZeroMemory(nameParts); + + // + return result; + } +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-bar.analyser.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 0000000..a9481fb --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,3454 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOI +// Description: Bar Analysing ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Extensions ... +void FillLiquidity( + XOHCL &lBar, + ENUM_X_DIRECTION lDir, + XBoxZone &lq, + datetime to // +) +{ + // + // Normalize Args ... + lq.Clean(); + to = NormalizeTime(to); + + // + // Validate Args ... + bool has = lBar.IsValid() && + HasDirection(lDir); + if (!has) + { + return; + } + + // + lq.to = to; + lq.dir = lDir; + lq.type = "XLQ"; + lq.from = lBar.time; + lq.symbol = lBar.symbol; + lq.period = lBar.period; + lq.upper = IsBullish(lDir) + ? lBar.GetDown() + : lBar.high; + lq.lower = IsBullish(lDir) + ? lBar.low + : lBar.GetUp(); +} + +// +// Implementations ... +class XCBarAnalyser : public XCBase +{ + // + public: + // + + // + // Constructor(s) ... + void XCBarAnalyser() + { + } + + // + // Deconstructor ... + void ~XCBarAnalyser() + { + } + + // + // Getter(s) / Setter(s) ... + + // + // Providers ... + + /** + * Calculate Loopback Data for Specific Bar ... + * + * @param index: Integer, Bar Current Index ... + * @param start: Integer, Start of Loopback ... + * @param end: Integer, End of Loopback ... + * @param count: Integer, Number of Calculating Bars ... + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * @return ( bool ) + */ + bool CalculateLoopbackData( + int &index, + int &start, + int &end, + int &count, + XOHCL &bar, + int loopback = 1 // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + index = -1; + start = -1; + end = -1; + count = -1; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + index = bar.Index(); + start = index + 1; + end = start + loopback; + count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Retrieve Loopback HH & LL Data ... + * + * @param hhIDX: Integer, HH Index ... + * @param hh: Double, HH Value ... + * @param llIDX: Integer, LL Index ... + * @param ll: Double, LL Value ... + * @param bar: XOHCL instance ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool CalculateLoopbackHLData( + int &hhIDX, + double &hh, + int &llIDX, + double &ll, + XOHCL &bar, + int loopback // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + int index = -1; + int start = -1; + int end = -1; + int count = -1; + result = CalculateLoopbackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + hhIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + count, + start // + ); + result = IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + llIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + count, + start // + ); + result = IsValidIndex(llIDX); + if (!result) + { + return result; + } + + // + hh = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + ll = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + return result; + } + + /** + * Fill Prices ... + * + * @param prices: double collection + * @param bar: XOHCL instance reference, Provides Start ... + * @param loopback: int, Specified How Many Bars Process ... + * @param type: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( bool ) + */ + int FillPrice( + double &prices[], + XOHCL &bar, + int loopback = 14, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + int result = 0; + + // + Clean(prices); + + // + loopback = NormalizeInt(loopback, 1); + + // + bool has = IsValid(type) && + bar.IsValid(); + if (!has) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + // Calculate Loopback Data ... + int index = -1; + int start = -1; + int end = -1; + int count = -1; + has = CalculateLoopbackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!has) + { + return result; + } + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + period, + i // + ); + if (!isInited) + { + // + iBar.Clean(); + continue; + } + + // + double iPrice = iBar.GetPrice(type); + + // + isInited = NotEmptyZero(iPrice); + if (isInited) + { + // + Add( + iPrice, + prices // + ); + } + + // + iBar.Clean(); + } + + // + result = ArraySize(prices); + has = result == count; + if (!has) + { + // + Clean(prices); + } + + // + ArrayReverse(prices); + + // + return result; + } + + /** + * Calculate Price Range ... + * + * @param ranges: double Collection, Calculated Ranges ... + * @param bar: XOHCL instance Reference, Start Bar ... + * @param forceBody: bool, Force to Calculate Range using Body ... + * @param forceDiff: bool, Force to Calculate Range using Onl Price Diff ... + * @param loopback: int, loopback period for Range Calculations ... + * + * @return ( int ) + */ + int GetPriceRange( + double &ranges[], + XOHCL &bar, + bool forceBody = false, + bool forceDiff = false, + int loopback = 14 // + ) + { + // + int result = 0; + + // + Clean(ranges); + + // + loopback = NormalizeInt(loopback, 1); + + // + if (!bar.IsValid()) + { + return result; + } + + // + bool has = false; + + // + // Select Uppers Prices ... + double uppers[]; + int uppersCount = 0; + if (forceBody) + { + // + has = FillPrice( + uppers, + bar, + loopback, + X_PRICE_UP // + ); + } + else + { + // + has = FillPrice( + uppers, + bar, + loopback, + X_PRICE_HIGH // + ); + } + if (has) + { + uppersCount = ArraySize(uppers); + } + + // + // Select Lower Prices ... + double lowers[]; + int lowersCount = 0; + if (forceBody) + { + // + has = FillPrice( + lowers, + bar, + loopback, + X_PRICE_DOWN // + ); + } + else + { + // + has = FillPrice( + lowers, + bar, + loopback, + X_PRICE_LOW // + ); + } + if (has) + { + lowersCount = ArraySize(lowers); + } + + // + // Validate Filled Prices ... + has = + IsValidSize(uppersCount) && + IsValidSize(lowersCount) && + uppersCount == lowersCount; + if (!has) + { + // + Clean(uppers); + Clean(lowers); + + // + return result; + } + + // + for (int i = 0; i < uppersCount; i++) + { + // + double iDiff = uppers[i] - lowers[i]; + double iValue = + forceDiff + ? iDiff + : lowers[i] + iDiff; + + // + Add( + iValue, + ranges // + ); + } + + // + result = ArraySize(ranges); + ArrayReverse(ranges); + + // + // Cleanup Resources ... + + // + Clean(uppers); + Clean(lowers); + + // + return result; + } + + /** + * Retrieve Price Velocities ... + * + * @param velocities: double Collection, Price Velocities ... + * @param bar: XOHCL instance Reference, Start Bar ... + * @param type: ENUM_X_PRICE member ... + * @param loopback: int, loopback period for Calculations ... + * + * @return ( int ) + */ + int GetPriceVelocity( + double &velocities[], + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int loopback = 14 // + ) + { + // + int result = 0; + + // + Clean(velocities); + loopback = NormalizeInt(loopback, 1); + + // + result = IsValid(type) && + bar.IsValid(); + + // + int to = bar.Index(); + int from = to + loopback; + for (int i = to; i < from; i++) + { + // + double iPrice = GetAppliedPrice( + bar.symbol, + bar.period, + i, + type // + ); + + // + double pPrice = GetAppliedPrice( + bar.symbol, + bar.period, + i + 1, + type // + ); + + // + double iVelocity = MathAbs(iPrice - pPrice); + Add( + iVelocity, + velocities // + ); + } + + // + result = ArraySize(velocities); + + // + return result; + } + + /** + * Calculate Price Change Percent ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param type: ENUM_X_PRICE member, Specified Price Type ... + * @param loopback: int, loopback period for Range Calculated ... + * + * @return ( double ) + */ + double GetPriceChangeRate( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_MEDIAN, + int loopback = 14 // + ) + { + // + double result = 0; + + // + bool has = false; + + // + loopback = NormalizeInt(loopback, 1); + + // + has = + bar.IsValid() && + IsValid(type); + if (!has) + { + return result; + } + + // + XOHCL oldBar; + has = oldBar.Init( + bar.symbol, + bar.period, + bar.Index() + loopback // + ); + if (!has) + { + // + oldBar.Clean(); + + // + return result; + } + double newPrice = bar.GetPrice(type); + double oldPrice = oldBar.GetPrice(type); + + // + result = ((newPrice - oldPrice) / oldPrice) / 100; + + // + oldBar.Clean(); + + // + return result; + } + + /** + * Detect Range Block ... + */ + bool DetectRangeBlocks( + XOHCL &bar, + XBoxZone &upper, + XBoxZone &lower, + int loopback = 288, + ENUM_SERIESMODE upperRangeUpperMode = MODE_HIGH, + ENUM_SERIESMODE upperRangeLowerMode = MODE_LOW, + ENUM_SERIESMODE lowerRangeUpperMode = MODE_HIGH, + ENUM_SERIESMODE lowerRangeLowerMode = MODE_LOW // + ) + { + // + bool result = false; + + // + // Normalize Args ... + upper.Clean(); + lower.Clean(); + loopback = NormalizeInt(loopback, 10); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + bar.Index() + loopback // + ); + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + double hhUpper = iBar.FindHighest(loopback, upperRangeUpperMode); + double hhLower = iBar.FindHighest(loopback, upperRangeLowerMode); + + // + double llUpper = iBar.FindLowest(loopback, lowerRangeUpperMode); + double llLower = iBar.FindLowest(loopback, lowerRangeLowerMode); + + // + double bhhUpper = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeUpperMode); + double bhhLower = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeLowerMode); + + // + double bllUpper = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeUpperMode); + double bllLower = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeLowerMode); + + // + hhUpper = MathMax(hhUpper, bhhUpper); + hhLower = MathMax(hhLower, bhhLower); + + // + llUpper = MathMin(llUpper, bllUpper); + llLower = MathMin(llLower, bllLower); + + // + datetime from = GetBarTime( + iBar.symbol, + iBar.period, + iBar.Index() + loopback // + ); + + // + upper.from = from; + upper.type = "XRNG"; + upper.to = bar.time; + upper.upper = hhUpper; + upper.lower = hhLower; + upper.symbol = iBar.symbol; + upper.period = iBar.period; + upper.dir = X_DIRECTION_BEARISH; + + // + lower.from = from; + lower.type = "XRNG"; + lower.to = bar.time; + lower.upper = llUpper; + lower.lower = llLower; + lower.symbol = iBar.symbol; + lower.period = iBar.period; + lower.dir = X_DIRECTION_BULLISH; + + // + result = upper.IsValid() && + lower.IsValid(); + if (!result) + { + // + iBar.Clean(); + upper.Clean(); + lower.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + /** + * Calculate Specified Bars Range Volume ... + * + * @param bar: XOHCL instance reference ... + * @param bullishVolume: double + * @param bearishVolume: double + * @param loopback: int + * + * @return ( bool ) + */ + bool CalculateRangeVolume( + XOHCL &bar, + double &bullishVolume, + double &bearishVolume, + int loopback = 5 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + bullishVolume = 0; + bearishVolume = 0; + loopback = NormalizeInt(loopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i <= end; i++) + { + // + iBar.Clean(); + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + // + iBar.Clean(); + + // + break; + } + + // + bool isBullish = iBar.IsBullish(); + bool isBearish = iBar.IsBearish(); + + // + if (isBullish) + { + bullishVolume += (double)iBar.volume; + } + else if (isBearish) + { + bearishVolume += (double)iBar.volume; + } + else + { + // + bullishVolume += (double)iBar.volume; + bearishVolume += (double)iBar.volume; + } + + // + iBar.Clean(); + } + + // + result = iBar.IsValid(); + + // + iBar.Clean(); + + // + return result; + } + + /** + * Detect Same Bars ... + * + * @param bar: XOHCL instance, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Holds Result Direction ... + * @param index: Integer, Holds Result Index ... + * @param sameBars: Iteger, Required Same Bar ... + * + * @return ( bool ) + */ + bool HasSameBars( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int &index, + int sameBars = 3 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + if (sameBars < 1) + { + sameBars = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + index = bar.Index() + 1; + bool canContinue = true; + int sameBullishBarsFounded = 0; + int sameBearishBarsFounded = 0; + bool canContinueForBullish = true; + bool canContinueForBearish = true; + while (canContinue) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + index // + ); + if (!result) + { + break; + } + + // + bool isBullish = iBar.IsBullish(); + bool isBearish = iBar.IsBearish(); + result = isBullish || + isBearish; + if (!result) + { + break; + } + + // + if (isBullish) + { + // + sameBullishBarsFounded++; + canContinueForBearish = false; + } + else if (isBearish) + { + // + sameBearishBarsFounded++; + canContinueForBullish = false; + } + else + { + // + sameBullishBarsFounded = 0; + sameBearishBarsFounded = 0; + canContinueForBullish = false; + canContinueForBearish = false; + } + + // + result = canContinueForBullish || + canContinueForBearish; + if (!result) + { + break; + } + + // + canContinueForBullish = + canContinueForBullish && + sameBullishBarsFounded > 0; + + // + canContinueForBearish = + canContinueForBearish && + sameBearishBarsFounded > 0; + + // + canContinue = + canContinueForBullish || + canContinueForBearish; + if (canContinue) + { + index++; + } + } + + // + bool hasBullishSameBars = + sameBullishBarsFounded >= sameBars; + + // + bool hasBearishSameBars = + sameBearishBarsFounded >= sameBars; + + // + result = hasBullishSameBars || + hasBearishSameBars; + if (!result) + { + return result; + } + + // + index--; + + // + dir = + hasBullishSameBars + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Check Fibonacci Level 382 Pressure ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool HasFiboPressure( + XOHCL &bar, + ENUM_X_DIRECTION forDir, + ENUM_X_FIBO_LEVELS level // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + double fiboLevelValue = GetFibonacciLevel( + bar.high, + bar.low, + level, + forDir // + ); + + // + bool isBullishPressured = + isBullish && + bar.GetDown() > fiboLevelValue; + bool isBearishPressured = + isBearish && + bar.GetUp() < fiboLevelValue; + + // + result = isBullishPressured || + isBearishPressured; + + // + return result; + } + + /** + * Detect Big Price Change Happens or not ... + * + * @param bar: XOHCL instance reference, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Event Direction ... + * @param rootIDX: int, Root of Momentum Index ... + * @param type: ENUM_X_PRICE member, Price Type ... + * @param forcBodyInRange: bool, Use Body in Range Detection ... + * @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ... + * + * @return ( bool ) + */ + bool IsSharp( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int &rootIDX, + ENUM_X_PRICE type = X_PRICE_CLOSE, + bool forcBodyInRange = true, + double rangeExtendMultiplier = 2.0 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1); + + // + result = + bar.IsValid() && + IsValid(type); + if (!result) + { + return result; + } + + // + double minPriceChangePercent = 0; + int loopback = GetPeriodSharpData( + minPriceChangePercent, + bar.period // + ); + + // + // Retrieve Price Change Percent ... + double priceChangePercent = GetPriceChangeRate( + bar, + type, + loopback // + ); + + // + // Velocities ... + double velocities[]; + int velocitiesCount = GetPriceVelocity( + velocities, + bar, + type, + loopback // + ); + double velocitiesAvg = GetAverage(velocities); + double oldPrice = GetAppliedPrice( + bar.symbol, + bar.period, + bar.Index() + loopback, + type // + ); + double newPrice = bar.GetPrice(type); + double currVelocity = MathAbs(oldPrice - newPrice); + + // + // Calculate HH and LL ... + + // + double hh = 0; + double ll = 0; + int hhIDX = -1; + int llIDX = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + result = + result && + ll > 0 && + hh > ll && + IsValidIndex(llIDX) && + IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + int hhDiff = (hhIDX - bar.Index()); + int llDiff = (llIDX - bar.Index()); + + // + // Bool Get Boundary Direction ... + + // + // Check Price Change Rate ... + + // + bool isBullish = + // + hhDiff <= 1 && + llIDX > hhIDX && + priceChangePercent > 0 && + priceChangePercent >= minPriceChangePercent && + currVelocity > (velocitiesAvg * rangeExtendMultiplier) + // + ; + + // + bool isBearish = + // + llDiff <= 1 && + hhIDX > llIDX && + priceChangePercent < 0 && + MathAbs(priceChangePercent) >= minPriceChangePercent && + currVelocity > (velocitiesAvg * rangeExtendMultiplier) + // + ; + + // + result = isBullish || + isBearish; + if (result) + { + // + rootIDX = + isBullish + ? llIDX + : hhIDX; + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + // + // Actions ... + + /** + * Check a Bar is End of an OrderBlock Bar or Not ... + * + * @param bar: XOHCL ... + * @param box: XBoxZone ... + * @param forceFVGBarType: bool, Force all Bars must be Same as Direction ... + * @param forceOBTwoBar: bool, Force Two Bars of OB Start must be InDirection ... + * + * @return ( bool ) + */ + bool IsOB( + XOHCL &bar, + XBoxZone &box, + bool forceFVGBarType = false, + bool forceOBTwoBar = false // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Bar Must be FVG ... + result = IsFVG( + bar, + box, + forceFVGBarType // + ); + if (!result) + { + // + box.Clean(); + + // + return result; + } + + // + box.type = "XOB"; + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // Order Block Includes an FVG which Starts by atleast One + // or More Indirectional Bars ... + XOHCL fvgLastBar; + XOHCL fvgLastBarPrev; + XOHCL fvgLastBarPrev2; + + // + int barIndex = bar.Index(); + int fvgLastBarIndex = barIndex + 3; + result = fvgLastBar.Init( + bar.symbol, + bar.period, + fvgLastBarIndex // + ); + result = + result && + fvgLastBar.GetPreviousBar(fvgLastBarPrev); + result = + result && + fvgLastBarPrev.GetPreviousBar(fvgLastBarPrev2); + if (!result) + { + // + box.Clean(); + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + fvgLastBarPrev2.Clean(); + + // + return result; + } + + // + // Check FVG Last Bar ... + + // + bool isBullishBlock = + isBullish && + (fvgLastBar.IsBearish() || + (fvgLastBar.IsBullish() && + fvgLastBarPrev.IsBearish())); + + // + bool isBearishBlock = + isBearish && + (fvgLastBar.IsBullish() || + (fvgLastBar.IsBearish() && + fvgLastBarPrev.IsBullish())); + + // + // Update Box ... + + // + if (isBullishBlock || + isBearishBlock) + { + // + box.from = fvgLastBar.time; + + // + box.lower = MathMin(box.lower, fvgLastBar.low); + box.upper = MathMax(box.upper, fvgLastBar.high); + } + + // + // Apply Force Two Bar ... + if (forceOBTwoBar) + { + // + isBullishBlock = + isBullishBlock && + fvgLastBarPrev.IsBearish(); + + // + isBearishBlock = + isBearishBlock && + fvgLastBarPrev.IsBullish(); + + // + // Update Box ... + if (isBullishBlock || + isBearishBlock) + { + // + box.from = fvgLastBarPrev.time; + box.lower = MathMin(box.lower, fvgLastBarPrev.low); + box.upper = MathMax(box.upper, fvgLastBarPrev.high); + } + } + + // + result = isBullishBlock || + isBearishBlock; + if (!result) + { + // + box.Clean(); + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + + // + return result; + } + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + + // + return result; + } + + /** + * Check a Bar is End of an FVG Bar or Not ... + * + * @param bar: XOHCL ... + * @param box: XBoxZone ... + * @param forceType: bool, Force all Bars must be Same as Direction ... + * + * @return ( bool ) + */ + bool IsFVG( + XOHCL &bar, + XBoxZone &box, + bool forceType = false // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + XOHCL p2Bar; + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + bool isBullish = p2Bar.high < bar.low; + bool isBearish = p2Bar.low > bar.high; + + // + result = isBullish || + isBearish; + + // + // Apply Force Type ... + if (result) + { + // + if (isBullish) + { + // + result = + bar.IsBullish() && + pBar.IsBullish() && + p2Bar.IsBullish(); + } + else if (isBearish) + { + // + result = + bar.IsBearish() && + pBar.IsBearish() && + p2Bar.IsBearish(); + } + } + + // + if (result) + { + // + box.to = bar.time; + box.from = p2Bar.time; + box.symbol = bar.symbol; + box.period = bar.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.upper = isBullish + ? bar.low + : p2Bar.low; + box.lower = isBullish + ? p2Bar.high + : bar.high; + box.type = "XFVG"; + } + + // + pBar.Clean(); + p2Bar.Clean(); + + // + result = box.IsValid(); + + // + return result; + } + + /** + * Check a Bar is a Trigger Box or Not ... + * + * @param bar: XOHCL instance Referernce, Specified Start Bar to Check ... + * @param trigger: XBoxZone instance Reference, Holds Detected Trigger Bar ... + * @param ob: XBoxZone instance Reference, Holds Detected Trigger Bar's OB ... + * @param fvg: XBoxZone instance Reference, Holds Detected Trigger Bar's FVG ... + * @param rLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Reversal Side Liquidity ... + * @param fLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Following Side Liquidity ... + * @param swingBar: XOHCL instance Referernce, Holds Detected Trigger Bar's Swing ... + * @param loopback: int, Loopback Bars Count ... + * @param maxAllowedRange: double, Max Allowed Trigger's OB Range ... + * @param minAllowedBlockEdgeLength: int, Min Allowed Block Edge Validation Length ... + * @param forceOBOppositBar: bool, Force OB to Start by Opposite Bar ... + * @param forceFVGBarType: bool, Force FVG to Has Same Bar Type ... + * @param forceGapBarBreakout: bool, Force Gap Bar Breakout OB Edge ... + * @param forceHasSwingBar: bool, Force Has Swing Bar ... + * @param forceHasLiquidity: bool, Force Has Following Liquidity ... + * @param forceHasReversalLiquidity: bool, Force Has Reversal Liquidity ... + * + * @return ( bool ) + */ + bool IsTrigger( + XOHCL &bar, + XBoxZone &trigger, + XBoxZone &ob, + XBoxZone &fvg, + XBoxZone &rLiquidity, + XBoxZone &fLiquidity, + XOHCL &swingBar, + int loopback = 10, + double maxAllowedRange = 0.0, + int minAllowedBlockEdgeLength = 0, + bool forceOBOppositBar = true, + bool forceFVGBarType = true, + bool forceGapBarBreakout = true, + bool forceHasSwingBar = true, + bool forceHasLiquidity = true, + bool forceHasReversalLiquidity = true // + ) + { + // + bool result = false; + + // + // Normalize Args ... + ob.Clean(); + fvg.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + loopback = NormalizeInt(loopback, 5); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + XOHCL tmpBar; + XOHCL tmpPBar; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + result = bar.GetPreviousBar(pBar); + + // + // Detect Base Order Block ... + result = + result && + // + // Order Block Detection ... + IsOB( + pBar, + ob, + forceFVGBarType, + forceOBOppositBar // + ) && + // + // Gap Detection ... + IsFVG( + pBar, + fvg, + forceFVGBarType // + ); + if (result) + { + // + trigger = ob; + trigger.type = "XTRG"; + } + + // + // Reading Requirements ... + + // + double points = GetPoints(bar.symbol); + + // + bool isBullish = ob.IsBullish(); + bool isBearish = ob.IsBearish(); + + // + int toIDX = trigger.ToIndex(); + int fromIDX = trigger.FromIndex(); + + // + // Validate Gaps Bar Breakeout ... + if (result && + forceGapBarBreakout) + { + // + // Extract Gap Bar ... + tmpBar.Clean(); + tmpPBar.Clean(); + result = + // + // Retrieve Bars ... + fvg.ToBar(tmpBar) && + tmpBar.GetPreviousBar(tmpPBar) && + // + // Validate Gap Bar is Momentum Bar ... + IsMomentum( + tmpPBar, + iDir, + 1 // + ) && + iDir == fvg.dir && + // + // Validate ... + (isBullish + ? tmpPBar.close > ob.upper + : tmpPBar.close < ob.lower); + + // + tmpBar.Clean(); + tmpPBar.Clean(); + } + + // + // Validate Range ... + if (result && + maxAllowedRange > 0) + { + // + double range = ob.GetRange(); + result = range <= (maxAllowedRange * points); + } + + // + // Validating Swing Bar ... + if (result && + forceHasSwingBar) + { + // + int swingIDX = -1; + result = ob.FromBar(tmpBar); + if (result) + { + // + // Detect Swing Bar Index ... + if (isBullish) + { + swingIDX = tmpBar.FindLowestIndex(loopback, MODE_LOW); + } + else if (isBearish) + { + swingIDX = tmpBar.FindHighestIndex(loopback, MODE_HIGH); + } + result = IsValidIndex(swingIDX); + if (result) + { + // + // Initialize Swing Bar ... + result = swingBar.Init( + bar.symbol, + bar.period, + swingIDX // + ); + } + + // + // Update Trigger Block based on Swing Bar ... + result = swingBar.IsValid(); + if (result) + { + // + // Update From ... + trigger.from = ((datetime)MathMin((int)trigger.from, (int)swingBar.time)); + + // + // Update Edge ... + if (isBullish) + { + trigger.lower = MathMin(trigger.lower, swingBar.GetDown()); + } + else if (isBearish) + { + trigger.upper = MathMax(trigger.upper, swingBar.GetUp()); + } + } + } + + // + tmpBar.Clean(); + } + + // + // Validate Min Block Edge ... + if (result && + minAllowedBlockEdgeLength > 0) + { + // + fromIDX = trigger.FromIndex(); + if (result) + { + // + // Looping Back ... + for (int i = fromIDX; i < fromIDX + minAllowedBlockEdgeLength; i++) + { + // + // Initialize i Bar ... + result = tmpBar.Init( + bar.symbol, + bar.period, + i // + ); + result = + result && + (isBullish + ? tmpBar.low > trigger.lower + : tmpBar.high > trigger.upper); + if (!result) + { + break; + } + + // + tmpBar.Clean(); + } + result = tmpBar.IsValid(); + + // + // Update Trigger Block ... + if (result) + { + trigger.from = ((datetime)(MathMin((int)trigger.from, (int)tmpBar.time))); + } + } + + // + tmpBar.Clean(); + } + + // + // Validating Liquidity ... + if (result && + (forceHasLiquidity || + forceHasReversalLiquidity)) + { + // + // Try to Detect Liquidity ... + toIDX = ob.ToIndex(); + for (int i = toIDX; i < toIDX + (loopback * 10); i++) + { + // + // Initialize i Bar ... + result = tmpBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + // Detect Liquidity ... + bool isRejected = + result && + IsRejected( + tmpBar, + iDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Validate Liquidities ... + if (isBullish) + { + // + if (isBullishRejected && + forceHasLiquidity && + !fLiquidity.IsValid() && + tmpBar.low < trigger.lower) + { + // + // Filling Following Liquidity ... + FillLiquidity( + tmpBar, + trigger.dir, + fLiquidity, + trigger.to // + ); + } + + // + if (isBearishRejected && + !rLiquidity.IsValid() && + forceHasReversalLiquidity && + tmpBar.high > trigger.upper) + { + // + // Filling Revrsal Liquidity ... + FillLiquidity( + tmpBar, + Opposit(trigger.dir), + rLiquidity, + trigger.to // + ); + } + } + else if (isBearish) + { + // + if (isBearishRejected && + forceHasLiquidity && + !fLiquidity.IsValid() && + tmpBar.high > trigger.upper) + { + // + // Filling Following Liquidity ... + FillLiquidity( + tmpBar, + trigger.dir, + fLiquidity, + trigger.to // + ); + } + + // + if (isBullishRejected && + !rLiquidity.IsValid() && + forceHasReversalLiquidity && + tmpBar.low < trigger.lower) + { + // + // Filling Reversal Liquidity ... + FillLiquidity( + tmpBar, + Opposit(trigger.dir), + rLiquidity, + trigger.to // + ); + } + } + + // + if ((!forceHasLiquidity + ? true + : fLiquidity.IsValid()) && + (!forceHasReversalLiquidity + ? true + : rLiquidity.IsValid())) + { + break; + } + + // + tmpBar.Clean(); + } + tmpBar.Clean(); + + // + result = (!forceHasLiquidity + ? true + : fLiquidity.IsValid()) && + (!forceHasReversalLiquidity + ? true + : rLiquidity.IsValid()); + } + + // + // Cleanup Resources ... + + // + pBar.Clean(); + tmpBar.Clean(); + tmpPBar.Clean(); + + // + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + return result; + } + + // + return result; + } + + // + // Candlestick ... + + /** + * Check Specified Bar is Doji Pattern or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param shadowMultiplier: double, Specified Shadow Multiplier ... + * + * @return ( bool ) + */ + bool IsDoji( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double shadowMultiplier = 1.5 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1.5, 3); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double body = bar.GetBody(); + double range = bar.GetRange(); + + // + result = + body > 0 && + range > 0 + ? (body / range < 0.1) + : false; + if (result) + { + // + dir = + bar.GetLowShadow() >= (bar.GetHighShadow() * shadowMultiplier) + ? X_DIRECTION_BULLISH + : bar.GetHighShadow() >= (bar.GetLowShadow() * shadowMultiplier) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + // + result = HasDirection(dir); + } + + // + return result; + } + + /** + * Check Specified Bar is Swing or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 7 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 1); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + // + pBar.Clean(); + ppBar.Clean(); + return result; + } + + // + bool isBullish = + // + pBar.low < bar.low && + pBar.low < ppBar.low && + bar.GetDown() > pBar.low + // + ; + + // + bool isBearish = + // + pBar.high > bar.high && + pBar.high > ppBar.high && + bar.GetUp() < pBar.high + // + ; + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + ppBar.Clean(); + int pBarIDX = pBar.Index(); + for (int i = pBarIDX + 1; i < pBarIDX + loopback; i++) + { + // + bool has = ppBar.Init( + pBar.symbol, + pBar.period, + i // + ); + + // + isBullish = + has && + isBullish && + pBar.low < ppBar.low; + + // + isBearish = + has && + isBearish && + pBar.high > ppBar.high; + } + + // + result = isBullish || + isBearish; + if (!result) + { + dir = X_DIRECTION_NONE; + } + } + + // + // Cleanup Resources ... + + // + pBar.Clean(); + ppBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar's Prev Bar is Simple Swing or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to it's Prev Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * + * @return ( bool ) + */ + bool IsSimpleSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + // Valdate Args ... + result = bar.IsValid(); + + // + // Reading Requirements ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + result = + bar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Now we Have to Check pBar is Swing Low or High ... + + // + bool isPBarSwingLow = + pBar.low < cBar.low && + pBar.low < p2Bar.low; + + // + bool isPBarSwingHigh = + pBar.high > cBar.high && + pBar.high > p2Bar.high; + + // + result = isPBarSwingLow || + isPBarSwingHigh; + if (result) + { + // + dir = isPBarSwingLow + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resourses ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Hammer Pattern or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param bodyMultiplier: double, Specified Body Multiplier ... + * + * @return ( bool ) + */ + bool IsHammer( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double bodyMultiplier = 2.0 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + bodyMultiplier = NormalizeDouble(bodyMultiplier, 1.5, 3); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double body = bar.GetBody(); + double lShadow = bar.GetLowShadow(); + double hShadow = bar.GetHighShadow(); + + // + bool isBullish = + hShadow < body && + lShadow > (bodyMultiplier * body); + + // + bool isBearish = + lShadow < body && + hShadow > (bodyMultiplier * body); + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specified Bar is Engulfed Prev Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * + * @return ( bool ) + */ + bool IsEngulfed( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + result = bar.GetBody() > pBar.GetBody(); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + bool isBullish = + bar.IsBullish() && + pBar.IsBearish() && + bar.GetDown() <= pBar.GetDown() && + bar.GetUp() > pBar.GetUp(); + + // + bool isBearish = + bar.IsBearish() && + pBar.IsBullish() && + bar.GetUp() >= pBar.GetUp() && + bar.GetDown() < pBar.GetDown(); + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + + // + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Momentum Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param forceBarType: bool, Force Apply Bar Type ... + * @param forceFiboPressure: bool, Force Apply Bar Type ... + * + * @return ( bool ) + */ + bool IsRejected( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + bool forceBarType = true, + bool forceFiboPressure = true // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + bool isBullish = + // + bar.low < pBar.low && + bar.GetShadows() > bar.GetBody() && + bar.GetLowShadow() > bar.GetBody() && + bar.GetLowShadow() > bar.GetHighShadow() + // + ; + + // + bool isBearish = + // + bar.high > pBar.high && + bar.GetShadows() > bar.GetBody() && + bar.GetHighShadow() > bar.GetBody() && + bar.GetHighShadow() > bar.GetLowShadow() + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Force Type ... + if (forceBarType) + { + // + isBullish = + isBullish && + bar.IsBullish(); + + // + isBearish = + isBearish && + bar.IsBearish(); + + // + result = isBullish || + isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + } + + // + // Check Force Fibo Pressure ... + if (forceFiboPressure) + { + // + bool hasBullishFiboPressure = + HasFiboPressure( + bar, + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_236 // + ); + + // + bool hasBearishFiboPressure = + HasFiboPressure( + bar, + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_236 // + ); + + // + isBullish = + isBullish && + hasBullishFiboPressure; + + // + isBearish = + isBearish && + hasBearishFiboPressure; + } + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Momentum Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsMomentum( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 2 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 1); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Calculate HH and LL ... + double hh = 0; + double ll = 0; + int hhIDX = -1; + int llIDX = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // s + ); + result = + result && + ll > 0 && + hh > ll && + IsValidIndex(llIDX) && + IsValidIndex(hhIDX); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + bool isBullish = + bar.low > ll && + bar.close >= hh && + bar.IsBullish() && + bar.low > pBar.low && + bar.high > pBar.high && + bar.GetBody() > pBar.GetBody() && + bar.GetRange() > pBar.GetRange() && + bar.GetShadows() < pBar.GetShadows(); + + // + bool isBearish = + bar.high < hh && + bar.close <= ll && + bar.IsBearish() && + bar.low < pBar.low && + bar.high < pBar.high && + bar.GetBody() > pBar.GetBody() && + bar.GetRange() > pBar.GetRange() && + bar.GetShadows() < pBar.GetShadows(); + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Pullback or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param loopback: int, Specified Loopback ... + * @param forceBody: bool, Force Using Body ... + * + * @return ( bool ) + */ + bool IsPullback( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3, + bool forceBody = false // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Bar Must Engulfed ... + result = IsEngulfed( + bar, + dir // + ); + if (!result) + { + return result; + } + + // + // Calculate HH and LL ... + double hh = 0; + double ll = 0; + int hhIDX = -1; + int llIDX = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + result = + result && + ll > 0 && + hh > ll && + IsValidIndex(llIDX) && + IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + bool isBullish = + bar.high > hh && + bar.low > ll; + + // + bool isBearish = + bar.high < hh && + bar.low < ll; + + // + result = isBullish || + isBearish; + if (result) + { + // + if (forceBody) + { + // + isBullish = + isBullish && + bar.GetUp() > hh && + bar.GetDown() > ll && + llIDX == bar.Index() + 1; + + // + isBearish = + isBearish && + bar.GetUp() < hh && + bar.GetDown() < ll && + hhIDX == bar.Index() + 1; + + // + result = isBullish || + isBearish; + } + + // + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + + // + return result; + } + + /** + * Check Specified Bar is Sequence Edge Breaker Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSeqBreakEdge( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Check Has Sequence or not ... + XOHCL pBar; + XOHCL iBar; + XOHCL iPBar; + bool has = false; + int index = bar.Index(); + int start = index + 1; + int end = start + loopback - 1; + bool hasBullishSeq = true; + bool hasBearishSeq = true; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar(s) ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + has = + has && + iBar.GetPreviousBar(iPBar); + + // + // Bullish Sequence ... + if (hasBullishSeq) + { + // + hasBullishSeq = + has && + iBar.low > iPBar.low; + } + + // + // Bearish Sequence ... + if (hasBearishSeq) + { + // + hasBearishSeq = + has && + iBar.high < iPBar.high; + } + + // + if (!hasBullishSeq && + !hasBearishSeq) + { + break; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + iBar.Clean(); + iPBar.Clean(); + + // + // Check a Sequence Detect ... + result = hasBullishSeq || + hasBearishSeq; + if (!result) + { + // + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + // + // Retrieve Previous Bar ... + result = bar.GetPreviousBar(pBar); + + // + // Now we Have Ensure has a Sequence ... + + // + isBullish = + result && + hasBearishSeq && + bar.high > pBar.high; + + // + isBearish = + result && + hasBullishSeq && + bar.low < pBar.low; + + // + // Summarizing Result ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Sequence Type Breaker Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSeqBreakType( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Check Has Sequence or not ... + XOHCL iBar; + bool has = false; + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + bool hasBullishSeq = true; + bool hasBearishSeq = true; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar(s) ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + + // + // Bullish Sequence ... + if (hasBullishSeq) + { + // + hasBullishSeq = + has && + iBar.IsBullish(); + } + + // + // Bearish Sequence ... + if (hasBearishSeq) + { + // + hasBearishSeq = + has && + iBar.IsBearish(); + } + + // + if (!hasBullishSeq && + !hasBearishSeq) + { + break; + } + + // + iBar.Clean(); + } + iBar.Clean(); + + // + // Check a Sequence Detect ... + result = hasBullishSeq || + hasBearishSeq; + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Now we Have Ensure has a Sequence ... + + // + isBullish = + result && + hasBearishSeq && + bar.IsBullish(); + + // + isBearish = + result && + hasBullishSeq && + bar.IsBearish(); + + // + // Summarizing Result ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Fully Sequence Breker Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSeqBreak( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Seq Edge ... + ENUM_X_DIRECTION seqEdgeDir; + bool isSeqEdgeBreaked = IsSeqBreakEdge( + bar, + seqEdgeDir // + ); + + // + // Check Seq Type ... + ENUM_X_DIRECTION seqTypeDir; + bool isSeqTypeBreaked = IsSeqBreakType( + bar, + seqTypeDir // + ); + + // + // Check Result ... + result = isSeqEdgeBreaked && + isSeqTypeBreaked && + seqEdgeDir == seqTypeDir; + if (result) + { + dir = seqEdgeDir; + } + + // + return result; + } + + // + // + // + + /** + * Check a Bar is Valid for Specified Direction of Positions ... + * + * @param bar: XOHCL instance, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Provide Direction ... + * + * @return ( bool ) + */ + bool IsValidForTrigger( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + bool allowCond1 = true, + bool allowCond2 = true, + bool allowCond3 = true, + bool allowCond4 = true, + bool allowCond5 = true, + bool allowCond6 = true, + bool allowCond7 = true // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Prepare Requirements ... + XOHCL pBar; + XOHCL p2Bar; + int loopback = 3; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Retrieve Bar's Prev ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + + // + // Handle Detect Trigger Bar ... + if (result) + { + // + // Check States ... + + // + // Rejected ... + bool isRejected = IsRejected( + pBar, + iDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Simple Rejected ... + bool isSimpleRejected = IsRejected( + pBar, + iDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + bool isSimpleBullishRejected = + isSimpleRejected && + IsBullish(iDir); + bool isSimpleBearishRejected = + isSimpleRejected && + IsBearish(iDir); + + // + // Full Directional Rejection ... + bool isFullRejected = IsRejected( + pBar, + iDir, + true, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isFullBullishRejected = + isFullRejected && + IsBullish(iDir); + bool isFullBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Engulfed ... + bool isEngulfed = IsEngulfed( + pBar, + iDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iDir); + + // + // Momentum ... + bool isMomentum = IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + + // + // Simple Swing ... + bool isSwing = IsSimpleSwing( + pBar, + iDir // + ); + bool isBullishSwing = + isSwing && + IsBullish(iDir); + bool isBearishSwing = + isSwing && + IsBearish(iDir); + + // + // Full Swing ... + bool isFullSwing = IsSwing( + pBar, + iDir, + 5 // + ); + bool isFullBullishSwing = + isFullSwing && + IsBullish(iDir); + bool isFullBearishSwing = + isFullSwing && + IsBearish(iDir); + + // + // Sequence Breaker ... + bool isSeqBreak = IsSeqBreak( + pBar, + iDir, + 3 // + ); + bool isBullishSeqBreak = + isSeqBreak && + IsBullish(iDir); + bool isBearishSeqBreak = + isSeqBreak && + IsBearish(iDir); + + // + // Now we have to Combine Conditions ... + + // + // Cond 1 ... + bool isBullishCond1 = false; + bool isBearishCond1 = false; + if (allowCond1) + { + // + // Bullish ... + isBullishCond1 = + // + isFullBullishRejected + // + ; + + // + // Bearish ... + isBearishCond1 = + // + isFullBearishRejected + // + ; + } + + // + // Cond 2 ... + bool isBullishCond2 = false; + bool isBearishCond2 = false; + if (allowCond2) + { + // + // Bullish ... + isBullishCond2 = + // + isBullishSwing && + isBullishRejected + // + ; + + // + // Bearish ... + isBearishCond2 = + // + isBearishSwing && + isBearishRejected + // + ; + } + + // + // Cond 3 ... + bool isBullishCond3 = false; + bool isBearishCond3 = false; + if (allowCond3) + { + // + // Bullish ... + isBullishCond3 = + // + isBullishSwing && + (isBullishRejected || + isBullishEngulfed || + isBullishMomentum) + // + ; + + // + // Bearish ... + isBearishCond3 = + // + isBearishSwing && + (isBearishRejected || + isBearishEngulfed || + isBearishMomentum) + // + ; + } + + // + // Cond 4 ... + bool isBullishCond4 = false; + bool isBearishCond4 = false; + if (allowCond4) + { + // + // Bullish ... + isBullishCond4 = + // + isBullishSwing && + isBullishSeqBreak && + (isBullishRejected || + isBullishEngulfed || + isBullishMomentum) + // + ; + + // + // Bearish ... + isBearishCond4 = + // + isBearishSwing && + isBearishSeqBreak && + (isBearishRejected || + isBearishEngulfed || + isBearishMomentum) + // + ; + } + + // + // Cond 5 ... + bool isBullishCond5 = false; + bool isBearishCond5 = false; + if (allowCond5) + { + // + // Bullish ... + isBullishCond5 = + // + isFullBullishSwing && + (isBullishRejected || + isBullishEngulfed || + isBullishMomentum) + // + ; + + // + // Bearish ... + isBearishCond5 = + // + isFullBearishSwing && + (isBearishRejected || + isBearishEngulfed || + isBearishMomentum) + // + ; + } + + // + // Cond 6 ... + bool isBullishCond6 = false; + bool isBearishCond6 = false; + if (allowCond6) + { + // + // Bullish ... + isBullishCond6 = + // + p2Bar.IsBearish() && + pBar.IsBullish() && + pBar.low < p2Bar.low && + pBar.high > p2Bar.high && + pBar.GetDown() <= p2Bar.GetDown() && + (isBullishEngulfed || + isBullishMomentum || + isSimpleBullishRejected) + // + ; + + // + // Bearish ... + isBearishCond6 = + // + p2Bar.IsBullish() && + pBar.IsBearish() && + pBar.high > p2Bar.high && + pBar.low < p2Bar.low && + pBar.GetUp() >= p2Bar.GetUp() && + (isBearishEngulfed || + isBearishMomentum || + isSimpleBearishRejected) + // + ; + } + + // + // Cond 7 ... + bool isBullishCond7 = false; + bool isBearishCond7 = false; + if (allowCond7) + { + // + // Bullish ... + isBullishCond7 = + // + p2Bar.IsBearish() && + pBar.IsBullish() && + pBar.low < p2Bar.low && + pBar.high > p2Bar.high && + pBar.GetUp() >= p2Bar.GetUp() + // + ; + + // + // Bearish ... + isBearishCond7 = + // + p2Bar.IsBullish() && + pBar.IsBearish() && + pBar.high > p2Bar.high && + pBar.low < p2Bar.low && + pBar.GetDown() <= p2Bar.GetDown() + // + ; + } + + // + // Summarizie Result ... + + // + isBullish = + // + isBullishCond1 || + isBullishCond2 || + isBullishCond3 || + isBullishCond4 || + isBullishCond5 || + isBullishCond6 || + isBullishCond7 + // + ; + + // + isBearish = + // + isBearishCond1 || + isBearishCond2 || + isBearishCond3 || + isBearishCond4 || + isBearishCond5 || + isBearishCond6 || + isBearishCond7 + // + ; + } + + // + // Summarize Result ... + result = (isBullish && + !isBearish) || + (isBearish && + !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-chart.helper.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-chart.helper.class.mq5 new file mode 100644 index 0000000..0f12015 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-chart.helper.class.mq5 @@ -0,0 +1,825 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCChartHelper +// Description: Chart Helper 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" + +// +// Implementation ... +class XCChartHelper : public XCBase +{ + // + // Public ... + public: + // + + // + // Constructor ... + XCChartHelper(ulong _chartId = 0) + { + // + // Normalize Chart ID ... + mChartID = NormalizeChartId(_chartId); + } + + // + // Desconstructor ... + ~XCChartHelper() + { + } + + // + // Actioins ... + + /** + * Redraw Specified Chart ... + */ + void Redraw() + { + ChartRedraw(mChartID); + } + + /** + * Chart Navigation ... + * + * @param position: ENUM_CHART_POSITION + * @param shift: int + * + * @return ( bool ) + */ + bool Navigate( + ENUM_CHART_POSITION position, + int shift // + ) + { + return (ChartNavigate(mChartID, position, shift)); + } + + /** + * Apply a Template to Chart ... + * + * @param filename: string file path ... + * + * @return ( bool ) + */ + bool ApplyTemplate(string filename) + { + return (ChartApplyTemplate(mChartID, filename)); + } + + /** + * Add Specified Indicator to Chart ... + * + * @param subWindow: int ... + * @param handle: int ... + * + * @return ( bool ) + */ + bool IndicatorAdd(int subWindow, int handle) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (ChartIndicatorAdd(mChartID, subWindow, handle)); + } + + /** + * Delete Specified Indicator from Chart ... + * + * @param subWindow: int ... + * @param name: string ... + * + * @return ( bool ) + */ + bool IndicatorDelete(int subWindow, string name) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (ChartIndicatorDelete(mChartID, subWindow, name)); + } + + /** + * Count all Charts Indicator ... + * + * @param subWindow: int ... + * + * @return ( int ) + */ + int IndicatorsTotal(int subWindow) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (ChartIndicatorsTotal(mChartID, subWindow)); + } + + /** + * Get Specified Indexed Indicator's Name ... + * + * @param subWindow: int ... + * @param index: int ... + * + * @return ( string ) + */ + string IndicatorName(int subWindow, int index) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (ChartIndicatorName(mChartID, subWindow, index)); + } + + /** + * Set Chart Symbol, Period ... + * + * @param symbol: string ... + * @param period: ENUM_TIMEFRAMES ... + * + * @return ( bool ) + */ + bool SetSymbolPeriod( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + return (ChartSetSymbolPeriod(mChartID, symbol, period)); + } + + /** + * Take an Screenshot of Chart ... + * + * @param filename: string file path ... + * @param width: int ... + * @param height: int ... + * @param align_mode: ENUM_ALIGN_MODE ... + * + * @return ( bool ) + */ + bool ScreenShot( + const string filename, + const int width, + const int height, + const ENUM_ALIGN_MODE align_mode // + ) const + { + return (ChartScreenShot(mChartID, filename, width, height, align_mode)); + } + + /** + * Writing parameters of chart to file ... + **/ + bool Save(const int file_handle) + { + // + string work_str; + int work_int; + + // + bool has = false; + + // + // Validate ... + if (file_handle == INVALID_HANDLE || mChartID == -1) + { + return has; + } + + // + // Write start marker - 0xFFFFFFFFFFFFFFFF ... + has = FileWriteLong(file_handle, -1) == sizeof(long); + if (!has) + { + return has; + } + + // + // Write chart type ... + has = FileWriteInteger(file_handle, Type(), INT_VALUE) == INT_VALUE; + if (!has) + { + return has; + } + + // + // Write chart symbol ... + work_str = Symbol(); + work_int = StringLen(work_str); + has = FileWriteInteger(file_handle, work_int, INT_VALUE) == INT_VALUE; + if (!has) + { + return has; + } + if (work_int != 0) + { + // + has = FileWriteString(file_handle, work_str, work_int) == work_int; + if (!has) + { + return has; + } + } + + // + // Write Period of chart ... + has = FileWriteInteger(file_handle, Period(), INT_VALUE) == sizeof(int); + if (!has) + { + return has; + } + + // + // Write value of the "Mode" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_MODE), INT_VALUE) == sizeof(int); + if (!has) + { + return has; + } + + // + // Write value of the "Foreground" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_FOREGROUND), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "Shift" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHIFT), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShiftSize" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHIFT), INT_VALUE) == sizeof(int); + if (!has) + { + return has; + } + + // + // Write value of the "AutoScroll" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_AUTOSCROLL), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "Scale" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALE), INT_VALUE) == sizeof(int); + if (!has) + { + return has; + } + + // + // Write value of the "ScaleFix" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALEFIX), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ScaleFix_11" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALEFIX_11), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "FixedMax" property ... + has = FileWriteDouble(file_handle, ChartGetDouble(mChartID, CHART_FIXED_MAX)) == sizeof(double); + if (!has) + { + return has; + } + + // + // Write value of the "FixedMin" property ... + has = FileWriteDouble(file_handle, ChartGetDouble(mChartID, CHART_FIXED_MIN)) == sizeof(double); + if (!has) + { + return has; + } + + // + // Write the "ScalePPB" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALE_PT_PER_BAR), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "PointsPerBar" property ... + has = FileWriteDouble(file_handle, ChartGetDouble(mChartID, CHART_POINTS_PER_BAR)) == sizeof(double); + if (!has) + { + return has; + } + + // + // Write value of the "ShowOHLC" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_OHLC), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShowLineBid" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_BID_LINE), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShowLineAsk" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_ASK_LINE), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShowLastLine" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_LAST_LINE), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShowPeriodSep" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_PERIOD_SEP), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShowGrid" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_GRID), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + // Write value of the "ShowVolumes" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_VOLUMES), INT_VALUE) == sizeof(int); + if (!has) + { + return has; + } + + // + // Write value of the "ShowObjectDescr" property ... + has = FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_OBJECT_DESCR), CHAR_VALUE) == sizeof(char); + if (!has) + { + return has; + } + + // + return has; + } + + /** + * Load Specified Chart File ... + * + * @param file_handle: int ... + * + * @return ( bool ) + */ + bool Load(const int file_handle) + { + // + string work_str; + int work_int; + + // + bool has = false; + + // + // Validate ... + if (file_handle == INVALID_HANDLE || mChartID == -1) + { + return has; + } + + // + // Read and checking start marker - 0xFFFFFFFFFFFFFFFF ... + if (FileReadLong(file_handle) != -1) + return has; + + // + // Read and checking chart type ... + if (FileReadInteger(file_handle, INT_VALUE) != Type()) + return has; + + // + // Read chart symbol ... + work_int = FileReadInteger(file_handle); + if (work_int != 0) + { + work_str = FileReadString(file_handle, work_int); + } + else + { + work_str = ""; + } + + // + // Read chart period ... + work_int = FileReadInteger(file_handle); + SetSymbolPeriod(work_str, (ENUM_TIMEFRAMES)work_int); + + // + // Read value of the "Mode" property ... + has = ChartSetInteger(mChartID, CHART_MODE, FileReadInteger(file_handle, INT_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "Foreground" property ... + has = ChartSetInteger(mChartID, CHART_FOREGROUND, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "Shift" property ... + has = ChartSetInteger(mChartID, CHART_SHIFT, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "ShiftSize" property ... + has = ChartSetInteger(mChartID, CHART_SHIFT, FileReadInteger(file_handle, INT_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "AutoScroll" property ... + has = ChartSetInteger(mChartID, CHART_AUTOSCROLL, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "Scale" property ... + has = ChartSetInteger(mChartID, CHART_SCALE, FileReadInteger(file_handle, INT_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "ScaleFix" property ... + has = ChartSetInteger(mChartID, CHART_SCALEFIX, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Read value of the "ScaleFix_11" property ... + has = ChartSetInteger(mChartID, CHART_SCALEFIX_11, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "FixedMax" property ... + has = ChartSetDouble(mChartID, CHART_FIXED_MAX, FileReadDatetime(file_handle)); + if (!has) + { + return has; + } + + // + // Rread value of the "FixedMin" property ... + has = ChartSetDouble(mChartID, CHART_FIXED_MIN, FileReadDatetime(file_handle)); + if (!has) + { + return has; + } + + // + // Rread value of the "ScalePPB" property ... + has = ChartSetInteger(mChartID, CHART_SCALE_PT_PER_BAR, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "PointsPerBar" property ... + has = ChartSetDouble(mChartID, CHART_POINTS_PER_BAR, FileReadDatetime(file_handle)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowOHLC" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_OHLC, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowLineBid" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_BID_LINE, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowLineAsk" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_ASK_LINE, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowLastLine" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_LAST_LINE, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowPeriodSep" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_PERIOD_SEP, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowGrid" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_GRID, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowVolumes" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_VOLUMES, FileReadInteger(file_handle, INT_VALUE)); + if (!has) + { + return has; + } + + // + // Rread value of the "ShowObjectDescr" property ... + has = ChartSetInteger(mChartID, CHART_SHOW_OBJECT_DESCR, FileReadInteger(file_handle, CHAR_VALUE)); + if (!has) + { + return has; + } + + // + return has; + } + + // + // Properties ... + + /** + * Get Chart ID ... + * + * @return ( ulong ) + */ + ulong ChartId() + { + return mChartID; + } + + /** + * Get Object Type ... + * + * @return ( int ) + **/ + int Type() const + { + return (0x1111); + } + + /** + * Get Chart Mode ... + * + * @return ( ENUM_CHART_MODE ) + **/ + ENUM_CHART_MODE Mode() + { + return ((ENUM_CHART_MODE)ChartGetInteger(mChartID, CHART_MODE)); + } + + /** + * Get Chart Symbol ... + * + * @return ( string ) + */ + string Symbol() + { + return (ChartSymbol(mChartID)); + } + + /** + * Get Chart Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES Period() + { + return (ChartPeriod(mChartID)); + } + + /** + * Count Chart Visible Bars ... + * + * @return ( int ) + */ + int VisibleBars() + { + return ((int)ChartGetInteger(mChartID, CHART_WIDTH_IN_BARS)); + } + + /** + * Get Chart First Visible Bars Index ... + * + * @return ( int ) + */ + int FirstVisibleBar() + { + return ((int)ChartGetInteger(mChartID, CHART_FIRST_VISIBLE_BAR)); + } + + /** + * Get Chart Last Visible Bars Index ... + * + * @return ( int ) + */ + int LastVisibleBar() + { + // + int first = FirstVisibleBar(); + int count = VisibleBars(); + int result = first + count; + return result; + } + + /** + * Get Chart's Specified SubWindows Minimum Price ... + * + * @param subWindow: int + * @return ( double ) + */ + double PriceMin(int subWindow = 0) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (ChartGetDouble(mChartID, CHART_PRICE_MIN, subWindow)); + } + + /** + * Get Chart's Specified SubWindows Maximum Price ... + * + * @param subWindow: int + * @return ( double ) + */ + double PriceMax(int subWindow = 0) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (ChartGetDouble(mChartID, CHART_PRICE_MAX, subWindow)); + } + + /** + * Get Chart Width in Pixel ... + * + * @param subWindow: int ... + * + * @return ( int ) + */ + int Width(int subWindow = 0) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (int)ChartGetInteger(mChartID, CHART_WIDTH_IN_PIXELS, subWindow); + } + + /** + * Get Chart Height in Pixel ... + * + * @param subWindow: int ... + * + * @return ( int ) + */ + int Height(int subWindow = 0) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (int)ChartGetInteger(mChartID, CHART_HEIGHT_IN_PIXELS, subWindow); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + ulong mChartID; // Chart ID ... +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-cobject.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..8846726 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,1439 @@ +/////////////////////////////////////////////////////// +// +// 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_BOX_OBJ = 7861, + X_BAR_ARROW_OBJ = 7862, + // + X_SIGNAL_OBJ = 8860, + X_OHCL_OBJ = 8863, + X_RR_OBJ = 8864, +}; + +enum ENUM_X_CHART_IDS +{ + X_AT, // AT + X_TO, // TO + X_FROM, // FROM + X_UPPER, // UPPER + X_LOWER, // LOWER + X_ENTRY, // ENTRY + X_TARGET, // TARGET + X_SL, // SL + X_TP, // TP + X_BAR_H_SHW, // HSHW + X_BAR_BDY, // BODY + X_BAR_L_SHW, // LSHW +}; + +string ToString(ENUM_X_CHART_IDS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +struct XPOIStyle +{ + // + // Properties ... + int width; + color clr; + ENUM_LINE_STYLE style; + + // + // Constructor ... + XPOIStyle() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup Model ... + void Clean() + { + // + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + ZeroMemory(this); + } + + // + // Default Props ... + void Default() + { + // + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + } +}; + +// +// Extensions ... + +/** + * Converts a XBoxZone struct to XSignal instance ... + * + * @param box: XBoxZone instance reference, provide source info ... + * @param signal: XSignal instance reference, holds prepared converted signal ... + * + * @return ( bool ) + */ +bool ToSignal( + XBoxZone &box, + XSignal &signal, + double &rewardRatios[], + double additionalSL = 0 // +) +{ + // + bool result = false; + + // + signal.Clean(); + + // + result = box.IsValid() && + HasChild(rewardRatios); + if (!result) + { + return result; + } + + // + XOHCL entryBar; + int entryIDX = box.ToIndex(); + if (entryIDX > 0) + { + entryIDX--; + } + result = entryBar.Init( + box.symbol, + box.period, + entryIDX // + ); + if (!result) + { + // + entryBar.Clean(); + + // + return result; + } + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + ENUM_POSITION_TYPE iType = + isBullish + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES iXType = + isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + double points = GetPoints(box.symbol); + + // + double entry = + isBullish + ? box.upper + : box.lower; + entry = entryBar.open; + + // + double sl = + isBullish + ? box.lower + : box.upper; + if (additionalSL > 0) + { + // + sl = + isBullish + ? sl - additionalSL + : sl + additionalSL; + } + + // + double risk = MathAbs(entry - sl); + + // + double tp = 0; + + // + // Calculate Target ... + XTarget targets[]; + + // + double tmp[]; + int idx = -1; + XTarget iTarget; + bool has = false; + double iRatio = 0; + double iReward = 0; + double iRewardPrice = 0; + Copy( + rewardRatios, + tmp // + ); + while (HasChild(tmp)) + { + // + idx = -1; + iRatio = GetMaxWidthIndex( + tmp, + idx // + ); + + // + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + has = iRatio > 0; + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + bool canSetTP = tp <= 0; + + // + iReward = iRatio * risk; + + // + iRewardPrice = + isBullish + ? entry + iReward + : entry - iReward; + if (canSetTP) + { + tp = iRewardPrice; + } + else + { + // + iTarget.target = iRewardPrice; + AddRef( + iTarget, + targets // + ); + + // + iTarget.Clean(); + } + } + Clean(tmp); + + // + // Filling Signal ... + signal.tp = tp; + signal.sl = sl; + signal.type = iType; + signal.comment = ""; + signal.entry = entry; + signal.time = box.to; + signal.volume = 0.01; + signal.provider = box.type; + signal.symbol = box.symbol; + signal.period = box.period; + signal.mode = X_ORDER_MODE_MARKET; + + // + if (HasChild(targets)) + { + // + Copy( + targets, + signal.targets // + ); + } + + // + result = signal.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + signal.Clean(); + } + + // + Clean(tmp); + Clean(targets); + iTarget.Clean(); + entryBar.Clean(); + + // + return result; +} + +// +// Implementation ... + +// +// Global Chart Objects ... + +// +// Bas Chart Object ... +class XCBaseObject : public CChartObject +{ + // + public: + // + + // + // Getter(s) / Setter(s) ... + + /** + * Get Object Specified Name ... + * + * @return ( string ) + */ + string ObjName() + { + return mObjName; + } + + /** + * Set Object Specified Name ... + * + * @param value: String ... + */ + void ObjName(string value) + { + mObjName = value; + } + + // + private: + // + + // + // Props ... + string mObjName; // Object Specified Name ... + + // +}; + +// +// Bar Arrow Object ... +class XCBarArrowObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * + * @return ( bool ) + */ + bool CreateByBar( + long chart_id, + string name, + int window, + int arrow, + XOHCL &bar, + ENUM_X_PRICE priceType, + double threshold = 5 // + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + IsValid(name) + // + ; + if (!result) + { + return result; + } + + // + datetime time = bar.time; + double price = bar.GetPrice(priceType); + + // + if (threshold > 0) + { + // + double thresholdPrice = threshold * GetPoints(bar.symbol); + if (priceType == X_PRICE_HIGH) + { + price += thresholdPrice; + } + else if (priceType == X_PRICE_LOW) + { + price -= thresholdPrice; + } + } + + // + result = mArrow.Create( + chart_id, + name, + window, + time, + price, + (char)arrow // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + // + // Setter(s) ... + + /** + * Set Arrow Anchor ... + * + * @param value: ENUM_ARROW_ANCHOR member ... + */ + void ArrowAnchor(ENUM_ARROW_ANCHOR value) + { + mArrow.Anchor(value); + } + + /** + * Set Arrow Color ... + * + * @param value: Color ... + */ + void ArrowColor(color value) + { + mArrow.Color(value); + } + + /** + * Set Arrow Width ... + * + * @param value: Integer ... + */ + void ArrowWidth(int value) + { + mArrow.Width(value); + } + + // + private: + // + CChartObjectArrow mArrow; + + // +}; + +// +// Signal ... +class XCSignalObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + void XCSignalObject() + { + } + + // + // Deconstructor ... + void ~XCSignalObject() + { + } + + /** + * Create a Signal Object on Chart ... + * + * @param chart_id: Long ... + * @param name: String ... + * @param window: Integer ... + * @param signal: XSignal instance ... + * @param length: int, Specified Length of Signal ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + const int window, + XSignal &signal, + int length = 3, + string prefix = NULL // + ) + { + // + bool result = false; + + // + length = NormalizeInt(length, 3); + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string name = signal.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + int delay = (PeriodSeconds(signal.period) * length); + datetime time1 = (datetime)((int)signal.time - delay); + datetime time2 = (datetime)((int)signal.time + delay); + + // + // TP ... + string tpName = ToString(X_TP) + "_" + nameMD5; + result = mTPTrend.Create( + chart_id, + tpName, + window, + time1, + signal.tp, + time2, + signal.tp // + ); + if (!result) + { + return result; + } + + // + // SL ... + string slName = ToString(X_SL) + "_" + nameMD5; + result = mSLTrend.Create( + chart_id, + slName, + window, + time1, + signal.sl, + time2, + signal.sl // + ); + if (!result) + { + // + mTPTrend.Delete(); + return result; + } + + // + // TARGET ... + bool hasTargets = HasChild(signal.targets); + if (hasTargets) + { + // + int targetsCount = ArraySize(signal.targets); + for (int i = 0; i < targetsCount; i++) + { + // + string targetName = ToString(X_TARGET) + "_" + ToXString(i) + "_" + nameMD5; + CChartObjectTrend *mTargetTrend; + mTargetTrend = new CChartObjectTrend(); + result = mTargetTrend.Create( + chart_id, + targetName, + window, + time1, + signal.targets[i].target, + time2, + signal.targets[i].target // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + break; + } + + // + mTargetTrends.Add(mTargetTrend); + } + } + + // + // ENTRY ... + string entrName = ToString(X_ENTRY) + "_" + nameMD5; + result = mEntryTrend.Create( + chart_id, + entrName, + window, + time1, + signal.entry, + time2, + signal.entry // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + mTargetTrends.Clear(); + return result; + } + + // + // Set Object Name ... + ObjName(name); + + // + return result; + } + + // + // Setter(s) ... + + // + // TP ... + + /** + * Set TP Width ... + * + * @param value: Integer ... + */ + void TPWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mTPTrend.Width(value); + } + + /** + * Set TP Color ... + * + * @param value: Color ... + */ + void TPColor(color value) + { + mTPTrend.Color(value); + } + + /** + * Set TP Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TPStyle(ENUM_LINE_STYLE value) + { + mTPTrend.Style(value); + } + + // + // SL ... + + /** + * Set SL Width ... + * + * @param value: Integer ... + */ + void SLWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSLTrend.Width(value); + } + + /** + * Set SL Color ... + * + * @param value: Color ... + */ + void SLColor(color value) + { + mSLTrend.Color(value); + } + + /** + * Set SL Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void SLStyle(ENUM_LINE_STYLE value) + { + mSLTrend.Style(value); + } + + // + // TARGET ... + + /** + * Set Target Width ... + * + * @param value: Integer ... + */ + void TargetWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Width(value); + } + } + + /** + * Set Target Color ... + * + * @param value: Color ... + */ + void TargetColor(color value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Color(value); + } + } + + /** + * Set Target Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TargetStyle(ENUM_LINE_STYLE value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Style(value); + } + } + + // + // ENTRY ... + + /** + * Set Entry Width ... + * + * @param value: Integer ... + */ + void EntryWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mEntryTrend.Width(value); + } + + /** + * Set Entry Color ... + * + * @param value: Color ... + */ + void EntryColor(color value) + { + mEntryTrend.Color(value); + } + + /** + * Set Entry Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void EntryStyle(ENUM_LINE_STYLE value) + { + mEntryTrend.Style(value); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SIGNAL_OBJ; + } + + // + private: + // + + // + CChartObjectTrend mTPTrend; + CChartObjectTrend mSLTrend; + CChartObjectTrend mEntryTrend; + CArrayObj mTargetTrends; +}; + +// +// XRR Object ... +class XCRRObject : public XCSignalObject +{ + // + // Public ... + public: + // + // Constructor ... + bool CreateBoxRR( + long chart_id, + const int window, + XBoxZone &box, + double &rewardRatios[], + int length = 3, + string prefix = NULL // + ) + { + // + bool result = false; + + // + length = NormalizeInt(length, 3); + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + XSignal signal; + result = ToSignal( + box, + signal, + rewardRatios // + ); + if (!result) + { + // + signal.Clean(); + + // + return result; + } + + // + result = Create( + chart_id, + window, + signal, + length, + prefix // + ); + + // + signal.Clean(); + + // + return result; + } +}; + +// +// OHCL, Bar Object ... +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; +}; + +// +// Box Object ...k +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, + datetime at, + 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) + { + // + if (IsValid(at)) + { + // + result = mAt.Create( + chart_id, + name + ToString(X_AT), + window, + at // + ); + } + + // + if (!result) + { + // + mAt.Detach(); + mAt.Delete(); + + // + mRect.Detach(); + mRect.Delete(); + } + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void BoxWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mAt.Width(value); + mRect.Width(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void BoxColor(color value) + { + // + mAt.Color(value); + mRect.Color(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BoxStyle(ENUM_LINE_STYLE value) + { + // + mAt.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 ... + CChartObjectVLine mAt; + CChartObjectRectangle mRect; +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-data.collector.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-data.collector.class.mq5 new file mode 100644 index 0000000..fb45c04 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-data.collector.class.mq5 @@ -0,0 +1,362 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCDataCollector ... +// Description: Class for Handling Data Read or Write ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Class for Handling Data Read or Write" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCDataCollector : public XCBase +{ + // + // Public ... + public: + // + // Constructors ... + XCDataCollector() + { + mPath = "XDataCollector"; + } + + // + // Deconstructor ... + ~XCDataCollector() + { + } + + // + // Properties ... + + // + string Path() + { + return mPath; + } + + // + void Path(string value) + { + mPath = value; + } + + // + // Tools ... + + // + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + (IsValid(mPath) ? mPath + "\\" : "") + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + int GetFileHandlerForWrite(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + // + int GetFileHandlerForRead(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT | FILE_ANSI // + ); + + // + return result; + } + + /** + * Save Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Save( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(fileName) && + IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Append Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Append( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(fileName) && + IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mHandler, 0, SEEK_END); + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Read Specified File Content ... + * + * @param fileName: string, file name ... + * @param content: string reference, hold's reading content ... + * + * @return ( bool ) + */ + bool Read( + string fileName, + string &content // + ) + { + // + bool result = false; + + // + // Normalize Args ... + content = NULL; + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Reading File ... + while (!FileIsEnding(mHandler)) + { + // + string iLine = FileReadString(mHandler); + content += iLine; + } + + // + // Close File ... + FileClose(mHandler); + + // + return result; + } + + /** + * Read Specified File Content ... + * + * @param fileName: string, file name ... + * @param content: string reference collection, hold's reading content lines ... + * + * @return ( bool ) + */ + bool Read( + string fileName, + string &content[] // + ) + { + // + bool result = false; + + // + // Normalize Args ... + Clean(content); + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Reading File ... + while (!FileIsEnding(mHandler)) + { + // + string iLine = FileReadString(mHandler); + Add( + iLine, + content // + ); + } + + // + // Close File ... + FileClose(mHandler); + + // + return result; + } + + /** + * Check Specified File Exists or not ... + * + * @param fileName: string, Full Path of File to Check ... + * + * @return ( bool ) + */ + bool IsExists(string fileName) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + // Check File Exists or not ... + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + FileClose(mHandler); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mPath; // Base Collector Path ... +}; diff --git a/BKPS/14040626/Classes/x-saherelm.x-guard.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-guard.class.mq5 new file mode 100644 index 0000000..d386123 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-guard.class.mq5 @@ -0,0 +1,1945 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXGuard ... +// Description: Guard Provider Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Guard Provider Class" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Libraries/x-saherelm.x-guard.lib.mq5" + +// +// Implementation ... +class XCGuard : public XCBase +{ + // + // public ... + public: + // + // Props ... + double minVolumeFactorForHedge; // Minimum Volume Factor for Hedge Profit Calculation ... + double minProfitPerVolumeFactorForHedge; // Minimum Required Profit per Volume Factor for Hedg ... + TOnGuarded onGuardEventListener; // On Guard Event Listener ... + + // + // Constructor(s) ... + XCGuard( + XCAlert *_alert, + XCTrade *_trader // + ) + { + // + alert = _alert; + trader = _trader; + + // + minVolumeFactorForHedge = 0.01; + minProfitPerVolumeFactorForHedge = 0.5; + } + + // + // Deconstructor(s) ... + ~XCGuard() + { + // + ZeroMemory(alert); + ZeroMemory(trader); + } + + // + // Tools ... + void DoGuards(XGuard &guards[]) + { + // + bool has = HasChild(guards); + if (!has) + { + return; + } + + // + XGuard tmp[]; + Copy( + guards, + tmp // + ); + while (HasChild(tmp)) + { + // + XGuard iGuard = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + // Do Guard Action ... + DoGuard(iGuard); + } + + // + Clean(tmp); + } + + // + void DoGuard(XGuard &guard) + { + // + bool has = false; + + // + // Validate and Do Guard ... + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Switch Based on Guard Action ... + switch (guard.action) + { + // + // Close ... + case X_GUARD_ACTION_CLOSE: + DoClose(guard); + break; + + // + // Close All ... + case X_GUARD_ACTION_CLOSE_ALL: + DoCloseAll(guard); + break; + + // + // Close All Long Positions ... + case X_GUARD_ACTION_CLOSE_LONGS: + DoCloseLongs(guard); + break; + + // + // Close All Short Positions ... + case X_GUARD_ACTION_CLOSE_SHORTS: + DoCloseShorts(guard); + break; + + // + // Close In Losts ... + case X_GUARD_ACTION_CLOSE_IN_LOSTS: + DoCloseInLosts(guard); + break; + + // + // Close In Profits ... + case X_GUARD_ACTION_CLOSE_IN_PROFITS: + DoCloseInProfits(guard); + break; + + // + // Close In Lost Longs ... + case X_GUARD_ACTION_CLOSE_IN_LOST_LONGS: + DoCloseInLostLongs(guard); + break; + + // + // Close In Profit Longs ... + case X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS: + DoCloseInProfitLongs(guard); + break; + + // + // Close In Lost Shorts ... + case X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS: + DoCloseInLostShorts(guard); + break; + + // + // Close In Profit Shorts ... + case X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT: + DoCloseInProfitShorts(guard); + break; + + // + // Partial Close ... + case X_GUARD_ACTION_PARTIAL_CLOSE: + DoPartialClose(guard); + break; + + // + // Trail Stop ... + case X_GUARD_ACTION_TRAIL_STOP: + DoTrailStop(guard); + break; + + // + // Trail Target ... + case X_GUARD_ACTION_TRAIL_TARGET: + DoTrailTarget(guard); + break; + + // + // Hedge Positions ... + case X_GUARD_ACTION_HEDGE: + DoHedge(guard); + break; + + // + } + } + + // + // protected ... + protected: + // + + // + bool GetPosition( + XPosition &position, + XGuard &guard // + ) + { + // + bool result = false; + + // + position.Clean(); + + // + result = + guard.IsValid() && + guard.ticket > 0; + if (!result) + { + return result; + } + + // + // Get Position ... + result = trader.GetPosition( + guard.ticket, + position // + ); + if (!result) + { + // + position.Clean(); + + // + return result; + } + + // + // Validate Position ... + result = + position.IsValid() && + position.symbol == guard.symbol && + position.provider == guard.provider && + position.period == guard.period; + if (!result) + { + // + position.Clean(); + + // + return result; + } + + // + return result; + } + + // + int GetPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + guard.symbol, + guard.provider, + guard.period, + NULL, // All Types ... + true, // Filter By Magc ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetLongPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + guard.symbol, + guard.provider, + guard.period, + X_POSITION_TYPE_LONG, // Specified Types ... + true, // Filter By Magc ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetShortPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + guard.symbol, + guard.provider, + guard.period, + X_POSITION_TYPE_SHORT, // Specified Types ... + true, // Filter By Magc ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInProfitPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInLostPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInProfitLongPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetLongPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInLostLongPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetLongPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInProfitShortPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetShortPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInLostShortPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetShortPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + // Guard Handlers ... + + // + void DoClose(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + NotEmpty(guard.ticket) && + guard.action == X_GUARD_ACTION_CLOSE; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + string comment = "Guard Close ..."; + + // + has = trader.Close( + position.ticket, + comment // + ); + if (has) + { + // + HandleNotifyPositionGuard(guard.action, position); + + // + string message = + "Guard Closed " + + ToXString(position.type) + + " Position (" + ToXString(position.ticket) + ") Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoCloseAll(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_ALL; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInLosts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOSTS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInLostPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Losts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " In Lost Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInProfits(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFITS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInProfitPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Profits ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " In Profit Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseLongs(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_LONGS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetLongPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close Longs ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " Long Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInLostLongs(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOST_LONGS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInLostLongPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Lost Longs ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " In Lost Longs Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInProfitLongs(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInProfitLongPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Profit Longs ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " In Profit Longs Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseShorts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetShortPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close Shorts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " Long Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInLostShorts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInLostShortPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Lost Shorts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " In Lost Shorts Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInProfitShorts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInProfitShortPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Profit Shorts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + // + string message = + "Guard Closed " + + ToXString(count) + + " In Profit Shorts Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoPartialClose(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + NotEmpty(guard.ticket) && + guard.volumeMultiplier > 0 && + guard.action == X_GUARD_ACTION_PARTIAL_CLOSE; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + // Normalize Volume Multiplier ... + double vMult = guard.volumeMultiplier; + if (vMult > 0.5) + { + vMult = 0.5; + } + if (vMult < 0) + { + vMult = 0.5; + } + + // + // Calculate and Normalize Volume ... + double volume = position.volume * vMult; + volume = NormalizeVolume( + volume, + position.symbol // + ); + + // + string comment = "Guard Partially Closed: " + ToXString(volume) + " ..."; + + // + has = trader.ClosePartial( + position.ticket, + volume, + comment // + ); + if (has) + { + // + HandleNotifyPositionGuard(guard.action, position); + + // + string message = + "Guard Closed Partially " + + ToXString(volume) + " of " + + ToXString(position.type) + + " Position (" + ToXString(position.ticket) + ") Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoTrailStop(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + guard.sl > 0 && + NotEmpty(guard.ticket) && + guard.action == X_GUARD_ACTION_TRAIL_STOP; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + bool isLong = IsLong(position.type); + + // + // Check Can Trail Stop or not ... + has = + // + // Position Exists ... + has && + // + // Positions in Profit for Trailling Stop ... + position.profit > 0 && + // + // Validate SL based on Position Type ... + (isLong + ? position.price > guard.sl && + (position.sl == 0 || + position.sl < guard.sl) + : position.price < guard.sl && + (position.sl == 0 || + position.sl > guard.sl)); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + string comment = "Guard Trail Stop ..."; + + // + has = trader.Modify( + position.ticket, + guard.sl, + position.tp, + comment // + ); + if (has) + { + // + HandleNotifyPositionGuard(guard.action, position); + + // + double before = NormalizePrice(position.sl, position.symbol); + double after = NormalizePrice(guard.sl, position.symbol); + + // + string message = + "Guard Trail Stop " + + ToXString(position.type) + + " Position (" + ToXString(position.ticket) + ")" + + " From: " + ToXString(before) + + "To: " + ToXString(after) + + " Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoTrailTarget(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + guard.tp > 0 && + NotEmpty(guard.ticket) && + guard.action == X_GUARD_ACTION_TRAIL_TARGET; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + bool isLong = IsLong(position.type); + + // + // Check Can Trail Stop or not ... + has = + // + // Position Exists ... + has && + // + // Check TP is not Same ... + guard.tp != position.tp && + // + // Validate TP based on Current Price ... + (isLong + ? guard.tp > position.price + : guard.tp < position.price); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + string comment = "Guard Trail Target ..."; + + // + has = trader.Modify( + position.ticket, + position.sl, + guard.tp, + comment // + ); + if (has) + { + // + HandleNotifyPositionGuard(guard.action, position); + + // + double before = NormalizePrice(position.tp, position.symbol); + double after = NormalizePrice(guard.tp, position.symbol); + + // + string message = + "Guard Trail Target " + + ToXString(position.type) + + " Position (" + ToXString(position.ticket) + ")" + + " From: " + ToXString(before) + + "To: " + ToXString(after) + + " Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoHedge(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + (guard.force + ? true + : (minVolumeFactorForHedge > 0 && + minProfitPerVolumeFactorForHedge > 0)) && + guard.action == X_GUARD_ACTION_HEDGE; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetPositions( + positions, + guard // + ); + has = HasChild(positions); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + // Calculate Positions Profits and Volumes ... + double swaps = 0; + double profits = 0; + double volumes = 0; + double commissions = 0; + for (int i = 0; i < count; i++) + { + // + swaps += positions[i].swap; + profits += positions[i].profit; + volumes += positions[i].volume; + commissions += positions[i].commission; + } + + // + // Check Profits and Volumes for Hedging ... + double hedgeValue = profits + (-1 * swaps) + commissions; + + // + // Check Force Hedging ... + if (!guard.force) + { + // + // Calculate Minimum Required Profit for Hedging ... + double minRequiredProfit = + (volumes / minVolumeFactorForHedge) * minProfitPerVolumeFactorForHedge; + + // + has = hedgeValue >= minRequiredProfit; + } + else + { + has = hedgeValue > 0; + } + + // + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Hedge ..."; + + // + // Loop through Positions and Close them One by One ... + // this is because of Trade Manager to Handle Close Trades ... + int closedCount = 0; + for (int i = 0; i < count; i++) + { + // + has = trader.Close( + positions[i].ticket, + comment // + ); + if (has) + { + closedCount++; + } + } + + // + has = IsValidSize(closedCount); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Hedge " + + ToXString(closedCount) + + " Positions by: " + + ToXString(hedgeValue) + + " Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + // private ... + private: + // + XCTrade *trader; + XCAlert *alert; + + // + void HandleNotifyPositionGuard( + ENUM_X_GUARD_ACTIONS action, + XPosition &position // + ) + { + // + if (!IsSpecifiedValid(action) || !position.IsValid() || onGuardEventListener == NULL) + { + return; + } + + // + XPosition positions[]; + AddRef( + position, + positions // + ); + HandleNotifyPositionsGuard(action, positions); + } + + // + void HandleNotifyPositionsGuard( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // + ) + { + // + if (!IsSpecifiedValid(action) || !HasChild(positions) || onGuardEventListener == NULL) + { + return; + } + + // + onGuardEventListener(action, positions); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-helper.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-helper.class.mq5 new file mode 100644 index 0000000..d1afd90 --- /dev/null +++ b/BKPS/14040626/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() + "|" + + ToXString(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/14040626/Classes/x-saherelm.x-http.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-http.class.mq5 new file mode 100644 index 0000000..631532f --- /dev/null +++ b/BKPS/14040626/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/14040626/Classes/x-saherelm.x-market.pattern.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-market.pattern.class.mq5 new file mode 100644 index 0000000..88bd8d3 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -0,0 +1,1483 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XCMarketPatternDetector +// 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" + +// +// Definitions ... + +// +// Implementation ... +class XCMarketPatternDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCMarketPatternDetector() + { + } + + // + // Deconstructor ... + ~XCMarketPatternDetector() + { + } + + // + // Actions / Helpers ... + + /** + * Check Specified Bar is Momentum Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param requiredBars: int, bar range for approve Momentum ... + * @param approvedMultiplier: int, a Multipler for approve Momentum ... + * + * @return ( bool ) + */ + bool IsMomentumBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int requiredBars = 3, + int approvedMultiplier = 2 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + requiredBars = NormalizeInt(requiredBars, 3, 10); + approvedMultiplier = NormalizeInt(approvedMultiplier, 2, 5); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + + // + XOHCL iBar; + bool has = false; + double rangeBody = 0; + int start = bar.Index() + 1; + int end = start + requiredBars; + for (int i = start; i < end; i++) + { + // + // Initialized Bar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + + // + // Summarize Body Sizes ... + if (has) + { + rangeBody += iBar.GetBody(); + } + + // + iBar.Clean(); + } + + // + // Calculate Body Approvement ... + result = bar.GetBody() >= (approvedMultiplier * rangeBody); + if (!result) + { + return result; + } + + // + // Check Direction ... + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Engulfed Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsEngulfedBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + + // + XOHCL iBar; + result = bar.GetPreviousBar(iBar); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Check Prev Bar Must Inside Bar ... + result = bar.GetUp() > iBar.GetUp() && + bar.GetDown() < iBar.GetDown(); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + iBar.IsBearish() && + bar.IsBullish(); + bool isBearish = + iBar.IsBullish() && + bar.IsBearish(); + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is True Gapped Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param approvedPointMultiplier: double, Gap Validation Multiplier in Point ... + * + * @return ( bool ) + */ + bool IsTrueGapedBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double approvedPointMultiplier = 1 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + approvedPointMultiplier = NormalizeDouble(approvedPointMultiplier, 1, 100); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + + // + XOHCL iBar; + result = bar.GetPreviousBar(iBar); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + iBar.IsBullish() && + bar.IsBullish(); + bool isBearish = + iBar.IsBearish() && + bar.IsBearish(); + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + double point = GetPoints(bar.symbol); + double approvedGapSize = approvedPointMultiplier * point; + + // + // Check Gap Exists ... + result = + isBullish + ? bar.low > iBar.high + : iBar.low > bar.high; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Validate Gap Size ... + double gapSize = isBullish + ? bar.low - iBar.high + : iBar.low - bar.high; + result = gapSize >= approvedGapSize; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Pinned Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param shadowApprovedMultiplier: int, Shadow Size Approve Multiplier ... + * @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ... + * @param forceDirection: bool, Apply Force Bar Type ... + * + * @return ( bool ) + */ + bool IsPinnedBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + shadowApprovedMultiplier = NormalizeInt(shadowApprovedMultiplier, 2, 5); + minimumPinBarRangeMultiplier = NormalizeDouble(minimumPinBarRangeMultiplier, 2, 100); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + double body = bar.GetBody(); + double lowShadow = bar.GetLowShadow(); + double highShadow = bar.GetHighShadow(); + + // + // Check Directions ... + bool isBullish = + lowShadow > body && + lowShadow > highShadow && + lowShadow >= (body * shadowApprovedMultiplier); + bool isBearish = + highShadow > body && + highShadow > lowShadow && + highShadow > (body * shadowApprovedMultiplier); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Checking Force Bar Type ... + if (forceDirection) + { + // + result = + isBullish + ? bar.IsBullish() + : bar.IsBearish(); + } + if (!result) + { + return result; + } + + // + // Check Range Validation ... + double point = GetPoints(bar.symbol); + double approvedRange = minimumPinBarRangeMultiplier * point; + result = bar.GetRange() >= approvedRange; + if (!result) + { + return result; + } + + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + + // + return result; + } + + /** + * Check Specified Bar has Star Pattern or not ... + * Morning Star => Bullish + * Evening Star => Bearish + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsStartPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Get Requirements ... + XOHCL pBar, p2Bar; + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Check Directions ... + bool isBullish = + bar.IsBullish() && + p2Bar.IsBearish(); + bool isBearish = + bar.IsBearish() && + p2Bar.IsBullish(); + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Checking Gap Exists Between Bars ... + result = + isBullish + ? p2Bar.GetDown() > pBar.GetUp() && + pBar.GetUp() < bar.GetDown() + : p2Bar.GetUp() < pBar.GetDown() && + pBar.GetDown() > bar.GetUp(); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Check Bar Close Validation ... + double barClosedApprovedPrice = p2Bar.GetDown() + ((p2Bar.GetUp() - p2Bar.GetDown()) / 2); + result = + isBullish + ? bar.close > barClosedApprovedPrice + : bar.close < barClosedApprovedPrice; + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Validating PBar Body and Shadow ... + double body = pBar.GetBody(); + double lowShadow = pBar.GetLowShadow(); + double highShadow = pBar.GetHighShadow(); + result = + body < bar.GetBody() && + body < p2Bar.GetBody() && + (isBullish + ? lowShadow > body && + lowShadow > highShadow + : highShadow > body && + highShadow > lowShadow); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Pirecing Pattern or not ... + * Piercing => Bullish + * Dark Cloud Cover => Bearish + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsPiercingPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + bar.IsBullish() && + pBar.IsBearish(); + bool isBearish = + bar.IsBearish() && + pBar.IsBullish(); + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Bar Close ... + double barCloseApprovedPrice = pBar.GetDown() + ((pBar.GetUp() - pBar.GetDown()) / 2); + result = + isBullish + ? bar.close > barCloseApprovedPrice + : bar.close < barCloseApprovedPrice; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Rising Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsRisingPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Required Bars ... + XOHCL iBar; + XOHCL bars[]; + bool has = false; + int start = bar.Index(); + int end = start + 5; + for (int i = start; i < end; i++) + { + // + // Initialized Bar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (has) + { + // + AddRef( + iBar, + bars // + ); + } + + // + iBar.Clean(); + } + result = ArraySize(bars) == 5; + if (!result) + { + // + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + // + // Check Directions ... + bool isBullish = + bars[0].IsBullish() && + bars[4].IsBullish() && + bars[1].IsBearish() && + bars[2].IsBearish() && + bars[3].IsBearish(); + bool isBearish = + bars[0].IsBearish() && + bars[4].IsBearish() && + bars[1].IsBullish() && + bars[2].IsBullish() && + bars[3].IsBullish(); + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + // + // Check Range Validation ... + double upper = bars[4].GetUp(); + double lower = bars[4].GetDown(); + + // + double max = MathMax(bars[1].GetUp(), bars[2].GetUp()); + max = MathMax(max, bars[3].GetUp()); + + // + double min = MathMin(bars[1].GetDown(), bars[2].GetDown()); + min = MathMin(min, bars[3].GetDown()); + + // + result = + max < upper && + min > lower && + (isBullish + ? bars[0].close > bars[4].GetUp() + : bars[0].close < bars[4].GetDown()); + if (!result) + { + // + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + /** + * Check Specified Bar has Flag Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param swingBar: XOHCL, Detected Swing Bar ... + * @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ... + * @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ... + * + * @return ( bool ) + */ + bool IsFlagPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XOHCL &swingBar, + int minimumPullbackBars = 3 // + ) + { + // + bool result = false; + + // + // Prepare ... + swingBar.Clean(); + CleanDirection(dir); + + // + // Normalizing ... + minimumPullbackBars = NormalizeInt(minimumPullbackBars, 3, 10); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + bar.IsBullish() && + bar.close > pBar.GetUp(); + bool isBearish = + bar.IsBearish() && + bar.close < pBar.GetDown(); + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Detect Swing Bar ... + ENUM_X_SWING_TYPE swingType = + isBullish + ? X_SWING_HIGH + : X_SWING_LOW; + result = + result && + IsXValid(swingType) && + bar.FindNextSwingBar( + swingType, + swingBar, + minimumPullbackBars // + ) && + (isBullish + ? swingBar.IsBullish() && + swingBar.high > pBar.high + : swingBar.IsBearish() && + swingBar.low < pBar.low); + if (!result) + { + // + pBar.Clean(); + swingBar.Clean(); + + // + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + if (!result) + { + swingBar.Clean(); + } + + // + return result; + } + + /** + * Check Specified Bar has SignalKey Bar Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param shadowApprovedMultiplier: int, Shadow Size Approve Multiplier ... + * @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ... + * @param forceDirection: bool, Apply Force Bar Type ... + * + * @return ( bool ) + */ + bool IsSignalKeyBarPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Get Requirements ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Chck Previous Bar must Pinned ... + result = IsPinnedBar( + pBar, + dir, + shadowApprovedMultiplier, + minimumPinBarRangeMultiplier, + forceDirection // + ); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Direction ... + bool isBullish = + bar.IsBullish() && + IsSpecifiedBullish(dir) && + bar.close > pBar.high; + bool isBearish = + bar.IsBearish() && + IsSpecifiedBearish(dir) && + bar.close < pBar.low; + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + + // + return result; + } + + // + // Trending ... + + /** + * Check Trend Exists Based on Swings ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param swings: XOHCL Array, Holds Swings ... + * @param numberOfSwings: int, Number of Swing Points for Detect Trend ... + * @param swingShoulders: int, Swing Shoulders Approvement Length ... + * + * @return ( bool ) + */ + bool HasSwingTrend( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XOHCL &swings[], + int numberOfSwings = 3, + int swingShoulders = 7 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + SpecifiedClean(swings); + + // + // Normalizing ... + numberOfSwings = NormalizeInt(numberOfSwings, 3, 10); + swingShoulders = NormalizeInt(swingShoulders, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Trend Direction ... + XOHCL iSwing; + int idx = -1; + bool has = false; + XOHCL swingLows[]; + XOHCL swingHighs[]; + int lastSwingLowIndex = bar.Index(); + int lastSwingHighIndex = bar.Index(); + while (ArraySize(swingLows) < numberOfSwings || ArraySize(swingHighs) < numberOfSwings) + { + // + bool canLookupSwingLow = ArraySize(swingLows) < numberOfSwings; + bool canLookupSwingHigh = ArraySize(swingHighs) < numberOfSwings; + if (!canLookupSwingLow && !canLookupSwingHigh) + { + break; + } + + // + // Handle Swing Lows ... + if (canLookupSwingLow) + { + // + iSwing.Clean(); + idx = FindXSwing( + X_SWING_LOW, + bar.symbol, + bar.period, + lastSwingLowIndex + 1, + swingShoulders // + ); + has = IsValidIndex(idx); + if (has) + { + // + has = iSwing.Init( + bar.symbol, + bar.period, + idx // + ); + if (has) + { + // + AddRef( + iSwing, + swingLows // + ); + + // + lastSwingLowIndex = idx; + } + } + } + + // + // Handle Swing Highs ... + if (canLookupSwingHigh) + { + // + iSwing.Clean(); + idx = FindXSwing( + X_SWING_HIGH, + bar.symbol, + bar.period, + lastSwingHighIndex + 1, + swingShoulders // + ); + has = IsValidIndex(idx); + if (has) + { + // + has = iSwing.Init( + bar.symbol, + bar.period, + idx // + ); + if (has) + { + // + AddRef( + iSwing, + swingHighs // + ); + + // + lastSwingHighIndex = idx; + } + } + } + } + + // + // Check Trend Based On Swings ... + + // + // Check Directions ... + + // + bool isBullish = false; + bool isBearish = false; + + // + datetime oldestSwingLow = NULL; + datetime oldestSwingHigh = NULL; + + // + // Checking Bullish Trend based on Swing Lows ... + int count = ArraySize(swingLows); + for (int i = 0; i < count - 1; i++) + { + // + has = swingLows[i].low > swingLows[i + 1].low; + isBullish = + !isBullish + ? has + : isBullish && has; + if (!isBullish) + { + break; + } + + // + datetime oldeTime = MathMin(swingLows[i].time, swingLows[i + 1].time); + oldestSwingLow = + !IsSpecifiedValid(oldestSwingLow) + ? oldeTime + : MathMin(oldestSwingLow, oldeTime); + } + + // + // Checking Bearish Trend based on Swing Highs ... + count = ArraySize(swingHighs); + for (int i = 0; i < count - 1; i++) + { + // + has = swingHighs[i].high < swingHighs[i + 1].high; + isBearish = + !isBearish + ? has + : isBearish && has; + if (!isBearish) + { + break; + } + + // + datetime oldeTime = MathMin(swingHighs[i].time, swingHighs[i + 1].time); + oldestSwingHigh = + !IsSpecifiedValid(oldestSwingHigh) + ? oldeTime + : MathMin(oldestSwingHigh, oldeTime); + } + + // + result = isBullish || isBearish; + if (!result) + { + // + iSwing.Clean(); + SpecifiedClean(swingLows); + SpecifiedClean(swingHighs); + + // + return result; + } + + // + if (isBullish && + isBearish && + IsSpecifiedValid(oldestSwingLow) && + IsSpecifiedValid(oldestSwingHigh)) + { + // + // Here we Have to Detect Newest Trend or Oldest Trend ... + isBullish = oldestSwingLow < oldestSwingHigh; + isBearish = oldestSwingHigh < oldestSwingLow; + } + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + // + iSwing.Clean(); + SpecifiedClean(swingLows); + SpecifiedClean(swingHighs); + + // + return result; + } + + // + if (isBullish) + { + // + Copy( + swingLows, + swings // + ); + + // + dir = X_DIRECTION_BULLISH; + } + else + { + // + Copy( + swingHighs, + swings // + ); + + // + dir = X_DIRECTION_BEARISH; + } + + // + iSwing.Clean(); + SpecifiedClean(swingLows); + SpecifiedClean(swingHighs); + + // + return result; + } + + bool HasSupport( + XOHCL &bar, + XOHCL &support, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + support.Clean(); + + // + // Normalizing ... + validationLength = NormalizeInt(validationLength, 7); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Find Support Swing ... + int idx = -1; + bool has = false; + int lookupIDX = bar.Index(); + while (!IsValidIndex(idx) && + lookupIDX < maxAllowedLoopback) + { + // + // Detect Swing ... + idx = FindXSwing( + X_SWING_LOW, + bar.symbol, + bar.period, + lookupIDX, + validationLength // + ); + has = IsValidIndex(idx); + if (!has) + { + // + lookupIDX++; + continue; + } + + // + // Retrieve Swing Bar ... + has = support.Init( + bar.symbol, + bar.period, + idx // + ); + if (!has) + { + // + idx = -1; + lookupIDX++; + support.Clean(); + continue; + } + + // + // Check Suppor Low Shadow ... + has = support.GetDown() < bar.low; + if (!has) + { + // + idx = -1; + lookupIDX++; + support.Clean(); + continue; + } + + // + if (IsValidIndex(idx)) + { + break; + } + } + + // + result = support.IsValid(); + + // + return result; + } + + bool HasResistance( + XOHCL &bar, + XOHCL &resistence, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + resistence.Clean(); + + // + // Normalizing ... + validationLength = NormalizeInt(validationLength, 7); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Find Support Swing ... + int idx = -1; + bool has = false; + int lookupIDX = bar.Index(); + while (!IsValidIndex(idx) && + lookupIDX < maxAllowedLoopback) + { + // + // Detect Swing ... + idx = FindXSwing( + X_SWING_HIGH, + bar.symbol, + bar.period, + lookupIDX, + validationLength // + ); + has = IsValidIndex(idx); + if (!has) + { + // + lookupIDX++; + continue; + } + + // + // Retrieve Swing Bar ... + has = resistence.Init( + bar.symbol, + bar.period, + idx // + ); + if (!has) + { + // + idx = -1; + lookupIDX++; + resistence.Clean(); + continue; + } + + // + // Check Resistance High Shadow ... + has = resistence.GetUp() > bar.high; + if (!has) + { + // + idx = -1; + lookupIDX++; + resistence.Clean(); + continue; + } + + // + if (IsValidIndex(idx)) + { + break; + } + } + + // + result = resistence.IsValid(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + + // + // Helpers ... + + /** + * Clean Specified Referenced Direction ... + * + * @param dir: ENUM_X_DIRECTION + */ + void CleanDirection(ENUM_X_DIRECTION &dir) + { + dir = X_DIRECTION_NONE; + } +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-md5.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-md5.class.mq5 new file mode 100644 index 0000000..6bd1c4e --- /dev/null +++ b/BKPS/14040626/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[], uint &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/14040626/Classes/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..ffb62ca --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,1085 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + +// +// Extensions ... + +void AddObjects( + CArrayObj *&source, + CArrayObj &dest // +) +{ + // + bool has = source != NULL && + source.Total() > 0; + if (!has) + { + return; + } + + // + for (int i = 0; i < source.Total(); i++) + { + dest.Add(source.At(i)); + } +} + +// +// Implementations ... +class XCPOIDrawer : public XCBase +{ + // + public: + // + // Props ... + + // + XPOIStyle defaultBullishStyle; + XPOIStyle defaultBearishStyle; + + // + XPOIStyle boxBullishStyle; + XPOIStyle boxBearishStyle; + + // + // Constructor ... + void XCPOIDrawer() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDrawer() + { + // + boxBullishStyle.Clean(); + boxBearishStyle.Clean(); + defaultBullishStyle.Clean(); + defaultBearishStyle.Clean(); + } + + // + // 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; + } + + // + // 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); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrLime; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrRed; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + } + + // + // Object Creators ... + + /** + * 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, + datetime at, + 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_" + + ToXString(upper) + "_" + + ToXString(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, + at, + 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 ignoreAt = true // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (ignoreAt) + { + box.at = NULL; + } + + // + int width = 1; + bool fill = false; + color clr = + box.IsBullish() + ? defaultBullishStyle.clr + : defaultBearishStyle.clr; + ENUM_LINE_STYLE style = STYLE_DASHDOTDOT; + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + box.at, + clr, + width, + fill, + style // + ); + + // + if (result) + { + // + if (box.IsBullish()) + { + // + ApplyStyle( + object, + boxBullishStyle // + ); + } + else + { + // + ApplyStyle( + object, + boxBearishStyle // + ); + } + } + + // + 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, + box.at, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal instance ... + */ + bool DrawSignal( + XSignal &signal, + XCSignalObject *&object, + int length = 3 // + ) + { + // + bool result = false; + + // + object = NULL; + length = NormalizeInt(length, 3); + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCSignalObject(); + result = object.Create( + chartID, + window, + signal, + length, + prefix // + ); + if (!result) + { + return result; + } + + // + object.TPWidth(1); + object.TPColor(clrGreen); + object.TPWidth(STYLE_DOT); + + // + object.SLWidth(1); + object.SLColor(clrRed); + object.SLWidth(STYLE_DOT); + + // + object.TargetWidth(1); + object.TargetColor(clrLightBlue); + object.TargetWidth(STYLE_DOT); + + // + object.EntryWidth(1); + object.EntryColor(clrYellow); + object.EntryWidth(STYLE_DOT); + + // + return result; + } + + /** + * Draw Trend Line based on Swings Points ... + * + * @param swings: XOHCL, Specified Swings ... + * @param dir: ENUM_X_DIRECTION, Specified Trend Direction ... + * @param rayRight: Ray to Right ... + * @param rayLeft: Ray to Left ... + * + * @return ( bool ) + */ + bool DrawSwingTrend( + XOHCL &swings[], + ENUM_X_DIRECTION dir, + CChartObjectTrend *&object, + bool rayRight = false, + bool rayLeft = false // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = HasChild(swings) && + count >= 2 && + HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isBullish = IsSpecifiedBullish(dir); + + // + double price1 = + isBullish + ? swings[0].low + : swings[0].high; + datetime time1 = swings[0].time; + + // + double price2 = + isBullish + ? swings[count - 1].low + : swings[count - 1].high; + datetime time2 = swings[count - 1].time; + + // + ulong chartId = ChartIdentification(); + int subWindow = SubWindowIdentification(); + string name = ToXString(dir) + "_Trend_" + ToXString(price1) + "_" + ToXString(price2); + + // + object = new CChartObjectTrend(); + result = object.Create( + chartId, + name, + subWindow, + time1, + price1, + time2, + price2 // + ); + if (result) + { + // + ApplyStyle( + object, + dir // + ); + + // + if (rayRight) + { + object.RayRight(true); + } + + // + if (rayLeft) + { + object.RayLeft(true); + } + } + + // + return result; + } + + /** + * Apply Specified Style to Object ... + */ + void ApplyStyle( + XCBoxObject *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.BoxColor(style.clr); + object.BoxWidth(style.width); + object.BoxStyle(style.style); + } + + /** + * Apply Specified Style to Object ... + */ + void ApplyStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Style to Specified Chart Object ... + * + * @param dir: Argument 2 + */ + void ApplyStyle( + CChartObject *object, + ENUM_X_DIRECTION dir // + ) + { + // + if (!HasDirection(dir)) + { + return; + } + + // + bool isBullish = IsSpecifiedBullish(dir); + if (isBullish) + { + // + object.Color(boxBullishStyle.clr); + object.Style(boxBullishStyle.style); + object.Width(boxBullishStyle.width); + } + else + { + // + object.Color(boxBearishStyle.clr); + object.Style(boxBearishStyle.style); + object.Width(boxBearishStyle.width); + } + } + + // + 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 ... + + // +}; \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-restrictions.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-restrictions.class.mq5 new file mode 100644 index 0000000..435b230 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-restrictions.class.mq5 @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCRestrictions +// Description: provides all Requirements for Apply Restrictions ... +// +// +// 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" + +// +// Definitions ... + +// +// All awailable Restrictions Period ... +enum ENUM_X_TRADE_RESTRICTIONS_PERIOD +{ + X_TRADE_RESTRICATION_NONE, // None + X_TRADE_RESTRICATION_HOURLY, // Per Hour + X_TRADE_RESTRICATION_DAILY, // Per Day + X_TRADE_RESTRICATION_WEEKLY, // Per Week + X_TRADE_RESTRICATION_MONTHLY, // Per Month +}; + +// +// Converts to String ... +string ToXString(ENUM_X_TRADE_RESTRICTIONS_PERIOD value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +// Check Has Restrictions or not ... +bool HasRestrictions(ENUM_X_TRADE_RESTRICTIONS_PERIOD value) +{ + // + bool result = false; + + // + result = value != X_TRADE_RESTRICATION_NONE; + + // + return result; +} + +// +// Implementation ... +class XCRestrictions : public XCBase +{ + // + // Public ... + public: + // + // Protected ... + protected: + // + // Private ... + private: + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-rm.panel.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-rm.panel.class.mq5 new file mode 100644 index 0000000..b8132b9 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-rm.panel.class.mq5 @@ -0,0 +1,1162 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCRMPanel +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-app-dialog.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +#include +#include +#include +#include +#include +#include + +// +// Implementation ... + +// +class XCRMPanel : public XCAppDialog +{ + // + public: + // + // Event Binding ... + // EVENT_MAP_BEGIN(XCRMPanel) + // ON_EVENT(ON_CLICK, btnBuy, HandleBtnBuyClicked) + // ON_EVENT(ON_CLICK, btnSell, HandleBtnSellClicked) + // EVENT_MAP_END(XCRMPanel) + + // + // Constructor(s) ... + void XCRMPanel() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCRMPanel() + { + // + HandleRemoveObjects(); + + // + ZeroMemory(mTrader); + } + + // + // Props ... + + // + int SubWindow() + { + return subWindow; + } + + // + void SubWindow(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + subWindow = value; + } + + // + // BUY ... + + // + string BtnBuyLabel() + { + return buyLabelStr; + } + + // + void BtnBuyLabel(string value) + { + buyLabelStr = value; + } + + // + color BtnBuyBGColor() + { + return btnBuyBGColor; + } + + // + void BtnBuyBGColor(color value) + { + btnBuyBGColor = value; + } + + // + // SELL ... + + // + string BtnSellLabel() + { + return sellLabelStr; + } + + // + void BtnSellLabel(string value) + { + sellLabelStr = value; + } + + // + color BtnSellBGColor() + { + return btnSellBGColor; + } + + // + void BtnSellBGColor(color value) + { + btnSellBGColor = value; + } + + // + double RiskPercent() + { + return riskPercent; + } + + // + void RiskPercent(double value) + { + // + if (value < minAllowedRiskPercent) + { + value = minAllowedRiskPercent; + } + + // + if (value > maxAllowedRiskPercent) + { + value = maxAllowedRiskPercent; + } + + // + riskPercent = value; + + // + tbRisk.Text((string)value); + } + + // + // + // + + bool HasSL() + { + return slLine != NULL; + } + + double ReadSL() + { + // + double result = 0; + + // + if (HasSL()) + { + // + result = slLine.GetDouble(OBJPROP_PRICE); + result = NormalizePrice(result, _Symbol); + } + + // + return result; + } + + bool HasTP() + { + return tpLine != NULL; + } + + double ReadTP() + { + // + double result = 0; + + // + if (HasTP()) + { + // + result = tpLine.GetDouble(OBJPROP_PRICE); + result = NormalizePrice(result, _Symbol); + } + + // + return result; + } + + bool HasEntry() + { + return entryLine != NULL; + } + + double ReadEntry() + { + // + double result = 0; + + // + if (HasEntry()) + { + // + result = entryLine.GetDouble(OBJPROP_PRICE); + result = NormalizePrice(result, _Symbol); + } + + // + return result; + } + + bool GetDirection(ENUM_X_DIRECTION &dir) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = HasTP() && + HasSL() && + HasEntry(); + + // + if (!result) + { + return result; + } + + // + double sl = ReadSL(); + double tp = ReadTP(); + double entry = ReadEntry(); + + // + result = sl > 0 && + tp > 0 && + entry > 0; + if (!result) + { + return result; + } + + // + bool isBullish = + tp > entry && + tp > sl && + entry > sl; + bool isBearish = + tp < entry && + tp < sl && + entry < sl; + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Tools ... + + // + void Default() + { + // + string prefix = CreateInstanceId(); + + // + defaultR2R = 2; + riskPercent = 1; + defaultRisk = 50; + minAllowedRiskPercent = 0.5; + maxAllowedRiskPercent = 10.0; + + // + disabledBtnColor = clrLightGray; + disabledBtnBGColor = clrGray; + + // + tbRiskID = prefix + "_RiskTB"; + + // + buyLabelStr = "Buy"; + btnBuyBGColor = clrLime; + btnBuyColor = clrDarkBlue; + btnBuyID = prefix + "_" + buyLabelStr; + + // + sellLabelStr = "Sell"; + btnSellBGColor = clrRed; + btnSellColor = clrDarkBlue; + btnSellID = prefix + "_" + sellLabelStr; + + // + slLine = NULL; + slColor = clrMagenta; + slID = prefix + "_SL"; + + // + tpLine = NULL; + tpColor = clrAqua; + tpID = prefix + "_TP"; + + // + entryLine = NULL; + entryColor = clrYellow; + entryID = prefix + "_Entry"; + + // + btnDrawRemoveID = prefix + "_DrawRemove"; + drawLabelStr = "Draw"; + removeLabelStr = "Remove"; + btnDrawColor = clrWhite; + btnDrawBGColor = clrDarkBlue; + btnRemoveColor = clrYellow; + btnRemoveBGColor = clrDarkRed; + + // + slippage = 10; + magicNumber = 1694056; + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + slippage, + magicNumber // + ); + } + + // + void UpdateState() + { + // + bool canEnable = HasSL() && + HasTP() && + HasEntry(); + + // + if (canEnable) + { + SetRemoveMode(); + } + else + { + SetDrawMode(); + } + + // + double entry = GetBid(_Symbol); + ENUM_X_DIRECTION dir; + if (GetDirection(dir)) + { + entry = GetEntry(_Symbol, dir); + } + + // + if (HasEntry()) + { + double iEntry = ReadEntry(); + if (iEntry != entry) + { + SetEntry(entry); + } + } + } + + // + // Handlers ... + + /** + * Handle Btn Buy Clicked ... + */ + void HandleBtnBuyClicked() + { + // + ENUM_X_DIRECTION dir; + bool has = GetDirection(dir); + bool isBullish = has & + IsBullish(dir); + if (!has || !isBullish) + { + return; + } + + // + double tp = ReadTP(); + double sl = ReadSL(); + double entry = ReadEntry(); + + // + mTrader.Buy( + _Symbol, + _Period, + volume, + entry, + sl, + tp // + ); + } + + /** + * Handle Btn Sell Clicked ... + */ + void HandleBtnSellClicked() + { + // + ENUM_X_DIRECTION dir; + bool has = GetDirection(dir); + bool isBearish = has & + IsBearish(dir); + if (!has || !isBearish) + { + return; + } + + // + double tp = ReadTP(); + double sl = ReadSL(); + double entry = ReadEntry(); + + // + mTrader.Sell( + _Symbol, + _Period, + volume, + entry, + sl, + tp // + ); + } + + /** + * Handle Draw Remove Position ... + */ + void HandleBtnDrawRemoveClicked() + { + // + string btnText = btnDrawRemove.Text(); + if (btnText == drawLabelStr) + { + HandleDrawObjects(); + } + else if (btnText == removeLabelStr) + { + HandleRemoveObjects(); + } + } + + /** + * Handle Risk Percent Changed ... + */ + void HandleOnRiskPercentChanged() + { + // + string tbRiskStr = tbRisk.Text(); + + // + double tbNewRisk = (double)tbRiskStr; + RiskPercent(tbNewRisk); + } + + // + // Virtuals ... + + // + virtual bool OnEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + // + bool result = false; + + // + XCAppDialog::OnEvent(id, lparam, dparam, sparam); + + // + // Check if the event is a button click + if (id == ON_CLICK + CHARTEVENT_CUSTOM) + { + // + // Verify if the clicked object is this button + if (lparam == btnBuy.Id()) + { + // + HandleBtnBuyClicked(); + result = true; + } + else if (lparam == btnSell.Id()) + { + // + HandleBtnSellClicked(); + result = true; + } + else if (lparam == btnDrawRemove.Id()) + { + // + HandleBtnDrawRemoveClicked(); + result = true; + } + } + else if (id == ON_END_EDIT + CHARTEVENT_CUSTOM) + { + // + if (lparam == tbRisk.Id()) + { + // + HandleOnRiskPercentChanged(); + result = true; + } + } + else if (id == CHARTEVENT_OBJECT_DRAG) + { + // + if (sparam == entryLine.Name()) + { + // + CalculateData(); + result = true; + } + else if (sparam == tpLine.Name()) + { + // + CalculateData(); + result = true; + } + else if (sparam == slLine.Name()) + { + // + CalculateData(); + result = true; + } + } + + // + return result; + } + + // + // Overrides ... + + // + bool Create( + const long chart, + const string name, + const int subwin, + const int x1, + const int y1, + const int x2, + const int y2 // + ) + { + // + bool result = false; + + // + // Create App Dialog instance it Self ... + result = XCAppDialog::Create( + chart, + name, + subwin, + x1, + y1, + x2, + y2 // + ); + if (!result) + { + return result; + } + + // + chartId = chart; + subWindow = subwin; + + // + // Configure Dialog ... + BackgroundColor(clrBlack); + + // + int top = Top(); + int left = Left(); + int right = Right(); + int bottom = Bottom(); + + // + int width = Width(); + int height = Height(); + + // + int desiredWidth = width - left; + int desiredHeight = height - top; + + // + int btnWidth = desiredWidth / 2; + int btnHeight = desiredHeight / 3; + + // + // Risk Edit ... + int tbRiskX1 = 0; + int tbRiskY1 = 0; + int tbRiskX2 = tbRiskX1 + (btnWidth * 2); + int tbRiskY2 = tbRiskY1 + btnHeight; + result = tbRisk.Create( + chart, + tbRiskID, + subWindow, + tbRiskX1, + tbRiskY1, + tbRiskX2, + tbRiskY2 // + ); + if (!result) + { + return result; + } + + // + result = tbRisk.Text((string)riskPercent); + result = tbRisk.TextAlign(ALIGN_CENTER); + + // + result = Add(tbRisk); + + // + // Create Draw/Remove Button ... + int btnDrawX1 = 0; + int btnDrawY1 = desiredHeight - (btnHeight * 2); + int btnDrawX2 = btnDrawX1 + (btnWidth * 2); + int btnDrawY2 = btnDrawY1 + btnHeight; + result = btnDrawRemove.Create( + chart, + btnDrawRemoveID, + subWindow, + btnDrawX1, + btnDrawY1, + btnDrawX2, + btnDrawY2 // + ); + if (!result) + { + return result; + } + + // + result = btnDrawRemove.Text(drawLabelStr); + result = btnDrawRemove.Color(btnDrawColor); + result = btnDrawRemove.ColorBackground(btnDrawBGColor); + + // + result = Add(btnDrawRemove); + + // + // Create Buy Button ... + int btnBuyX1 = 0; + int btnBuyY1 = desiredHeight - btnHeight; + int btnBuyX2 = btnBuyX1 + btnWidth; + int btnBuyY2 = btnBuyY1 + btnHeight; + result = btnBuy.Create( + chart, + btnBuyID, + subWindow, + btnBuyX1, + btnBuyY1, + btnBuyX2, + btnBuyY2 // + ); + if (!result) + { + return result; + } + + // + result = btnBuy.Text(buyLabelStr); + result = btnBuy.Color(btnBuyColor); + result = btnBuy.ColorBackground(btnBuyBGColor); + + // + result = Add(btnBuy); + + // + // Create Sell Button ... + int btnSellX1 = btnBuyX2; + int btnSellY1 = btnBuyY1; + int btnSellX2 = btnSellX1 + btnWidth; + int btnSellY2 = btnSellY1 + btnHeight; + result = btnSell.Create( + chart, + btnSellID, + subWindow, + btnSellX1, + btnSellY1, + btnSellX2, + btnSellY2 // + ); + if (!result) + { + return result; + } + + // + result = btnSell.Text(sellLabelStr); + result = btnSell.Color(btnSellColor); + result = btnSell.ColorBackground(btnSellBGColor); + + // + result = Add(btnSell); + + // + if (result) + { + // + UpdateState(); + CalculateData(); + } + + // + return result; + } + + // + protected: + // + XCTrade *mTrader; + int slippage; + long magicNumber; + + // + long chartId; + int subWindow; + + // + string slID; + color slColor; + CChartObjectHLine *slLine; + + // + string tpID; + color tpColor; + CChartObjectHLine *tpLine; + + // + string entryID; + color entryColor; + CChartObjectHLine *entryLine; + + // + double riskPercent; + double minAllowedRiskPercent; + double maxAllowedRiskPercent; + + // + double volume; + + // + double defaultR2R; + double defaultRisk; + + // + color disabledBtnColor; + color disabledBtnBGColor; + + // + // Risk Percent Edit ... + CEdit tbRisk; + string tbRiskID; + + // + // BUY Button ... + CButton btnBuy; + string btnBuyID; + string buyLabelStr; + color btnBuyColor; + color btnBuyBGColor; + + // + // SELL Button ... + CButton btnSell; + string btnSellID; + string sellLabelStr; + color btnSellColor; + color btnSellBGColor; + + // + // DRAW / REMOVE Button ... + CButton btnDrawRemove; + string btnDrawRemoveID; + string drawLabelStr; + string removeLabelStr; + color btnDrawColor; + color btnDrawBGColor; + color btnRemoveColor; + color btnRemoveBGColor; + + // + private: + // + + bool EnableBuy(bool value) + { + // + bool result = false; + + // + btnBuy.Locking(!value); + btnSell.Pressed(value); + if (!value) + { + // + // Disabled ... + btnBuy.Color(disabledBtnColor); + btnBuy.ColorBackground(disabledBtnBGColor); + } + else + { + // + // Enable ... + btnBuy.Color(btnBuyColor); + btnBuy.ColorBackground(btnBuyBGColor); + } + + // + return result; + } + + bool EnableSell(bool value) + { + // + bool result = false; + + // + btnSell.Locking(!value); + btnSell.Pressed(value); + if (!value) + { + // + // Disabled ... + btnSell.Color(disabledBtnColor); + btnSell.ColorBackground(disabledBtnBGColor); + } + else + { + // + // Enable ... + btnSell.Color(btnSellColor); + btnSell.ColorBackground(btnSellBGColor); + } + + // + return result; + } + + bool SetDrawMode() + { + // + bool result = false; + + // + result = btnDrawRemove.Text(drawLabelStr); + result = btnDrawRemove.Color(btnDrawColor); + result = btnDrawRemove.ColorBackground(btnDrawBGColor); + + // + return result; + } + + bool SetRemoveMode() + { + // + bool result = false; + + // + result = btnDrawRemove.Text(removeLabelStr); + result = btnDrawRemove.Color(btnRemoveColor); + result = btnDrawRemove.ColorBackground(btnRemoveBGColor); + + // + return result; + } + + void HandleDrawObjects() + { + // + double entry = GetBid(_Symbol); + double points = GetPoints(_Symbol); + double riskRatio = defaultRisk * points; + double rewardRatio = riskRatio * defaultR2R; + double sl = entry - riskRatio; + double tp = entry + rewardRatio; + + // + datetime rectTime1 = iTime( + _Symbol, + _Period, + 20 // + ); + datetime rectTime2 = iTime( + _Symbol, + _Period, + 19 // + ); + + // + bool has = false; + + // + // Create Entry Line ... + entryLine = new CChartObjectHLine(); + has = entryLine.Create( + chartId, + entryID, + subWindow, + entry // + ); + if (!has) + { + // + HandleRemoveObjects(); + return; + } + entryLine.Selectable(false); + entryLine.Color(entryColor); + + // + // Create SL Line ... + slLine = new CChartObjectHLine(); + has = slLine.Create( + chartId, + slID, + subWindow, + sl // + ); + if (!has) + { + // + HandleRemoveObjects(); + return; + } + slLine.Color(slColor); + slLine.Selectable(true); + + // + // Create TP Line ... + tpLine = new CChartObjectHLine(); + has = tpLine.Create( + chartId, + tpID, + subWindow, + tp // + ); + if (!has) + { + // + HandleRemoveObjects(); + return; + } + tpLine.Color(tpColor); + tpLine.Selectable(true); + + // + CalculateData(); + } + + void HandleRemoveObjects() + { + // + if (HasSL()) + { + // + slLine.Delete(); + slLine.Detach(); + ZeroMemory(slLine); + } + + // + if (HasTP()) + { + // + tpLine.Delete(); + tpLine.Detach(); + ZeroMemory(tpLine); + } + + // + if (HasEntry()) + { + // + entryLine.Delete(); + entryLine.Detach(); + ZeroMemory(entryLine); + } + + // + UpdateState(); + CalculateData(); + } + + void CalculateData() + { + // + EnableBuy(false); + EnableSell(false); + + // + ENUM_X_DIRECTION dir; + bool has = GetDirection(dir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(dir); + bool isBearish = IsBearish(dir); + + // + if (isBullish) + { + // + EnableBuy(true); + EnableSell(false); + } + else if (isBearish) + { + // + EnableSell(true); + EnableBuy(false); + } + + // + double sl = ReadSL(); + double tp = ReadTP(); + double entry = ReadEntry(); + double points = GetPoints(_Symbol); + + // + double risk = MathAbs(entry - sl); + int riskPoints = (int)(risk / points); + double riskRewardRatio = MathAbs(tp - entry) / risk; + riskRewardRatio = NormalizeDouble(riskRewardRatio, 2); + + // + double balance = GetBalance(); + + // + double riskAmount = riskPercent * (balance / 100); + riskAmount = NormalizePrice(riskAmount, _Symbol); + + // + double rewardAmount = riskAmount * riskRewardRatio; + rewardAmount = NormalizePrice(rewardAmount, _Symbol); + + // + string currency = mTrader.mAccount.GetCurrency(); + + // + volume = mTrader + .mAccount + .CalculateVolume( + _Symbol, + riskAmount, + riskPoints // + ); + volume = NormalizeVolume(volume, _Symbol); + + // + string slDesc = "SL: " + ToXString(sl) + + ", Risk: " + ToXString(riskPoints) + " pt (" + ToXString(riskPercent) + "%)" + + ", Amount: " + ToXString(riskAmount) + currency; + slLine.Tooltip(slDesc); + slLine.Description(slDesc); + + // + string tpDesc = "TP: " + ToXString(tp) + " (" + ToXString(rewardAmount) + " " + currency + ")" + + ", R2R: 1:" + ToXString(riskRewardRatio); + tpLine.Tooltip(tpDesc); + tpLine.Description(tpDesc); + + // + string entryDesc = "Entry: " + ToXString(entry) + + ", Volume: " + ToXString(volume); + entryLine.Tooltip(entryDesc); + entryLine.Description(entryDesc); + + // + } + + void SetEntry(double value) + { + // + if (value <= 0 || + !HasEntry()) + { + return; + } + + // + bool has = entryLine + .SetDouble(OBJPROP_PRICE, value); + } + + double GetBalance() + { + // + double result = 0; + + // + // TODO: Change This ... + return mTrader.mAccount.GetBalance(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-trade-manager.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-trade-manager.class.mq5 new file mode 100644 index 0000000..b1b3d3b --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-trade-manager.class.mq5 @@ -0,0 +1,2329 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XCXTradeManager +// Description: provides all Trade Management 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-alert.class.mq5" +#include "../Classes/x-saherelm.x-data.collector.class.mq5" +#include "../Classes/x-saherelm.x-guard.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" + +// +// Implementation ... +class XCTradeManager : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAlert *alert; + XCGuard *guard; + XCTrade *trader; + XCVolume *volume; + XTimeTracker timeTracker; + XCDataCollector *collector; + + // + XCPOIDrawer *drawer; + + // + TCheckForGuard checkForGuardEventListener; + + // + // Constructor ... + XCTradeManager( + XCAlert *_alert, + XCTrade *_trader, + XCVolume *_volume, + XCGuard *_guard // + ) + { + // + alert = _alert; + guard = _guard; + volume = _volume; + trader = _trader; + + // + drawer = new XCPOIDrawer(); + + // + allowTrade = true; + allowLongs = true; + allowShorts = true; + + // + reportTrades = true; + reportSignals = true; + reportProtector = true; + reportAfterTradesBalance = true; + + // + SaveTrades(false); + + // + collector = new XCDataCollector(); + + // + // Setting Collector Path ... + string mPath = (IsValid(alert.GetPrefix()) + ? alert.GetPrefix() + "\\" + : "") + + trader.mAccount.GetCompany(); + collector.Path(mPath); + } + + // + // Deconstructor ... + ~XCTradeManager() + { + // + Clean(trades); + + // + timeTracker.Clean(); + + // + ZeroMemory(alert); + ZeroMemory(trader); + + // + delete drawer; + ZeroMemory(drawer); + + // + delete collector; + ZeroMemory(collector); + } + + // + // Properties ... + + // + bool SaveTrades() + { + return mSaveTrades; + } + + // + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + // + bool SaveSignals() + { + return mSaveSignals; + } + + // + void SaveSignals(bool value) + { + mSaveSignals = value; + } + + // + bool SaveWins() + { + return mSaveWins; + } + + // + void SaveWins(bool value) + { + mSaveWins = value; + } + + // + bool SaveLosts() + { + return mSaveLosts; + } + + // + void SaveLosts(bool value) + { + mSaveLosts = value; + } + + // + bool SaveRestrictions() + { + return mSaveRestrictions; + } + + // + void SaveRestrictions(bool value) + { + mSaveRestrictions = value; + } + + // + // Setter(s) ... + + // + void SetSymbolConfigurations(string symbolConfiguration) + { + // + int count = 0; + bool has = false; + + // + // If Not Provided ... + has = IsSpecifiedValid(symbolConfiguration); + if (!has) + { + // + AddDefaultSymbolConfiguration(); + return; + } + + // + // Try to Parse Data ... + string symbolData[]; + count = SplitContent( + symbolData, + symbolConfiguration, + "]" // + ); + has = IsValidSize(count); + if (!has) + { + // + AddDefaultSymbolConfiguration(); + + // + SpecifiedClean(symbolData); + return; + } + + // + // Loop through Exists Symbol Data's ... + for (int i = 0; i < count; i++) + { + // + string iData = symbolData[i]; + + // + // Extract Data Parts ... + string iParts[]; + int iPartsCount = SplitContent( + iParts, + iData, + "|" // + ); + has = IsValidSize(iPartsCount); + if (has) + { + // + // Determines Required Parts ... + bool hasSymbol = iPartsCount >= 1; + bool hasPeriod = iPartsCount >= 2; + bool hasSessionsDescriptor = iPartsCount >= 3; + bool hasMaxAllowedSpred = iPartsCount >= 4; + bool hasMaxAllowedPositios = iPartsCount >= 5; + bool hasRestrictionDescriptor = iPartsCount >= 6; + + // + // Extract Symbol ... + string iSymbol = + hasSymbol + ? iParts[0] + : _Symbol; + iSymbol = EscapeString(iSymbol); + iSymbol = NormalizeSymbol(iSymbol); + + // + // Extract Period ... + ENUM_TIMEFRAMES iPeriod = + hasPeriod + ? ToPeriod(EscapeString(iParts[1])) + : _Period; + iPeriod = NormalizePeriod(iPeriod); + + // + // Extract Max Allowed Sspread ... + double iMaxAllowedSpread = + hasMaxAllowedSpred + ? (double)(EscapeString(iParts[3])) + : 25; + + // + // Extract Max Allowedd Positions ... + int iMaxAllowedPositions = + hasMaxAllowedPositios + ? (int)(EscapeString(iParts[4])) + : 5; + + // + // Extract Sessions Descriptor ... + string iSessionsDescriptor = + hasSessionsDescriptor + ? iParts[2] + : ""; + iSessionsDescriptor = EscapeString(iSessionsDescriptor); + + // + // Extract Restrictions Descriptor ... + string iRestrictionsDescriptor = + hasRestrictionDescriptor + ? iParts[5] + : ""; + iRestrictionsDescriptor = EscapeString(iRestrictionsDescriptor); + + // + XSymbolTradeConfig iConfig; + + // + // Initialize Config ... + has = iConfig.Init( + iSymbol, + iPeriod, + iSessionsDescriptor, + iMaxAllowedSpread, + iMaxAllowedPositions, + iRestrictionsDescriptor // + ); + if (has) + { + AddOrUpdateSymbolConfiguration(iConfig); + } + + // + // Cleanup Resources ... + iConfig.Clean(); + } + + // + // Cleanup Resources ... + SpecifiedClean(iParts); + } + + // + // Cleanup Resources ... + SpecifiedClean(symbolData); + } + + // + int FillSymbolConfigurations(XSymbolTradeConfig &dest[]) + { + // + SpecifiedClean(dest); + + // + Copy( + symbolTradeConfigs, + dest // + ); + + // + int result = ArraySize(dest); + + // + return result; + } + + // + void SetTradeReports( + bool _reportTrades, + bool _reportSignals, + bool _reportProtector, + bool _reportRestrictions, + bool _reportAfterTradesBalance // + ) + { + // + reportTrades = _reportTrades; + reportSignals = _reportSignals; + reportProtector = _reportProtector; + reportRestrictions = _reportRestrictions; + reportAfterTradesBalance = _reportAfterTradesBalance; + } + + // + void SetTradePermissions( + bool _allowTrade, + bool _allowLongs, + bool _allowShorts // + ) + { + // + allowTrade = _allowTrade; + allowLongs = _allowLongs; + allowShorts = _allowShorts; + } + + // + // Tools and Helpers ... + + /** + * Do All Position Managing Senaros ... + */ + void Manage() + { + // + // Handle Restrictions ... + HandleRestrictions(); + + // + // Check Contains Trades for Managing ... + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + // Update Required Infos of Trades ... + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + // Update Trade Data ... + trades[i].swap = iPosition.swap; + trades[i].profit = iPosition.profit; + } + + // + // Do Trade Protection ... + Protect(); + } + + /** + * Do All Position Protection Here ... + */ + void Protect() + { + // + string prefix = "Protector: "; + int targetDistance = 5; + + // + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + XPosition ownPosition[]; + XPosition ownLongPosition[]; + XPosition ownShortPosition[]; + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = + trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + AddRef( + iPosition, + ownPosition // + ); + + // + if (IsLong(iPosition.type)) + { + // + AddRef( + iPosition, + ownLongPosition // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPosition // + ); + } + } + + // + has = HasChild(ownPosition); + if (!has) + { + // + Clean(ownPosition); + Clean(ownLongPosition); + Clean(ownShortPosition); + + // + return; + } + + // + XGuard guards[]; + int guardsCount = CheckForGuard(guards); + bool hasGuard = IsValidSize(guardsCount); + if (hasGuard) + { + // + guard.DoGuards(guards); + } + + // + double swapSum = 0; + double profitSum = 0; + double commissionSum = 0; + + // + // Calculate Required Data On Collection ... + count = ArraySize(ownPosition); + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPosition[i]; + + // + swapSum += iPosition.swap; + profitSum += iPosition.profit; + commissionSum += iPosition.commission; + } + + // + // Do Collection Protectiong ... + + // + // Handle Force Close At Time ... + has = HandleForceCloseAtTime(); + if (has) + { + // + Clean(ownPosition); + Clean(ownLongPosition); + Clean(ownShortPosition); + + // + return; + } + + // + // Do Signle Protections ... + for (int i = 0; i < count; i++) + { + // + // Select Position ... + XPosition iPosition = ownPosition[i]; + int idx = -1; + has = HasTrade( + idx, + iPosition.ticket // + ); + if (!has) + { + continue; + } + + // + bool isLong = IsLong(iPosition.type); + double points = GetPoints(iPosition.symbol); + + // + // Handle RF On Targets ... + if (iPosition.profit > 0) + { + // + // Handle Risk Free On Targets ... + XTarget targets[]; + Copy( + trades[idx].signal.targets, + targets // + ); + int targetsCount = ArraySize(targets); + has = IsValidSize(targetsCount); + if (has) + { + // + for (int j = 0; j < targetsCount; j++) + { + // + XTarget jTarget = targets[j]; + + // + int appliedTargetIDX = -1; + + // + // Check Target is Applied Before or Not ... + has = + !trades[idx].signal.isTargetApplied + ? true + : trades[idx].signal.appliedTargetIDX < j; + if (!has) + { + continue; + } + + // + // Check Traget Validation ... + has = + iPosition.sl == 0 + ? true + : isLong + ? iPosition.sl < jTarget.target + : iPosition.sl > jTarget.target; + if (!has) + { + continue; + } + + // + double targetDelta = isLong + ? jTarget.target + (targetDistance * points) + : jTarget.target - (targetDistance * points); + + // + // Can Risk Free ... + bool canRF = + jTarget.doRF && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + + // + // Can Partial Close ... + bool canPC = + jTarget.volumeMultiplier > 0 && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + bool canRFPC = canRF || + canPC; + if (canRFPC) + { + // + // Handle Risk Free ... + bool isRFDone = false; + if (canRF) + { + // + double tp = iPosition.tp; + double sl = jTarget.target; + string comment = "RF On Target ..."; + isRFDone = trader.Modify( + iPosition.ticket, + sl, + tp, + comment // + ); + } + + // + // Handle Partail Close ... + bool isPCDone = false; + if (canPC) + { + // + double _volume = jTarget.volumeMultiplier * iPosition.volume; + _volume = NormalizeVolume(_volume, iPosition.symbol); + string comment = "RF On Target ..."; + isPCDone = trader.ClosePartial( + iPosition.ticket, + _volume, + comment // + ); + } + + // + // Handle Report Action ... + bool isRFPCDone = isRFDone || + isPCDone; + if (isRFPCDone) + { + // + trades[idx].signal.appliedTargetIDX = j; + trades[idx].signal.isTargetApplied = true; + + // + string message = prefix + + ToXString(iPosition.type) + + " Position: " + + ToXString(iPosition.ticket) + + (isRFDone ? " RF" : "") + + (isPCDone ? " PC" : "") + + " On Traget: " + ToXString(jTarget.target) + + " Successfully ..."; + HandleReportProtector(message); + } + } + } + } + } + } + } + + /** + * Check Can Analyse Market based on Configurations ... + * + * @param symbol: Symbol + * @param period: Period + * @param time: Analysing Time + * + * @return ( bool ) + */ + bool CanAnalyse( + string symbol, + ENUM_TIMEFRAMES period, + datetime time // + ) + { + // + bool result = false; + + // + // Finding Symbol Configuration Index ... + int idx = FindSymbolConfigurationIndex( + symbol, + period // + ); + + // + // If Not Exists ... + if (!IsValidIndex(idx)) + { + // + result = true; + return result; + } + + // + // If Exists ... + + // + // Check Session is Active ... + result = symbolTradeConfigs[idx].CanTrade(time); + if (!result) + { + return result; + } + + // + // Check Symbol Restrictions ... + result = symbolTradeConfigs[idx].IsRestricted(time); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check Signal Execution Conditions ... + * + * @param signal: XSignal instance reference ... + * @param executionResult: ENUM_X_SIGNAL_EXECUTION_RESULT member reference ... + * + * @return ( bool ) + */ + bool CheckSignal( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &executionResult // + ) + { + // + bool result = false; + + // + // Cleanup ... + executionResult = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Reporting Signal ... + if (reportSignals) + { + // + string message = signal.GetMessage("Provided"); + alert.SendAlert(message); + } + + // + SaveSignal(signal); + + // + // Check Trade Permission ... + result = AllowTrade(signal.type); + if (!result) + { + // + result = false; + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + // Check Sessions and Restrictions ... + result = CanAnalyse( + signal.symbol, + signal.period, + signal.time // + ); + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + + // + return result; + } + + // + return result; + } + + /** + * Check Allow Trade or not .. + * + * @param type: ENUM_POSITIO_TYPE + * + * @return ( bool ) + */ + bool AllowTrade(ENUM_POSITION_TYPE type) + { + // + bool result = false; + + // + result = allowTrade; + if (!result) + { + return result; + } + + // + result = + (IsLong(type) && allowLongs) || + (IsShort(type) && allowShorts); + + // + return result; + } + + /** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCATBEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ + bool Execute(XSignal &signal) + { + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = HasTrade( + idx, + signal // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT executionResult; + + // + // Checking Signal For Execution ... + result = CheckSignal( + signal, + executionResult // + ); + if (result) + { + // + result = trader.ExecuteSignal( + signal, + executionResult // + ); + } + + // + // Alert Signal Execution ... + if (reportTrades) + { + // + string executionMessage = ToString(executionResult); + + // + string message = NULL; + if (result) + { + message = signal.GetMessage("Executed"); + } + else + { + message = signal.GetMessage("Failed due (" + executionMessage + ")"); + } + + // + alert.SendAlert(message); + } + + // + if (result) + { + // + // TODO: Complete this ... + + // + // Create Trade Struct ... + XTradeInfo iTrade; + + // + ulong positionID = trader.GetLastOpenPositionTicket(); + double commission = trader.GetPositionCommission(positionID); + + // + iTrade.signal = signal; + iTrade.positionID = positionID; + iTrade.commission = commission; + iTrade.signaledAt = signal.time; + iTrade.executedAt = TimeCurrent(); + iTrade.conditions = signal.conditions; + + // + AddRef( + iTrade, + trades // + ); + } + + // + return result; + } + + /** + * Retrieve Specified Positions ... + * + * @param positions: XPosition instance Reference Array, which holds Founded Positions ... + * @param symbol: string, Specified Symbol Name ... + * @param provider: string, Specified Provider Name ... + * @param period: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetPositions( + XPosition &positions[], + string symbol, + string provider, + ENUM_TIMEFRAMES period // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = + IsValid(symbol) && + IsValid(period) && + IsValid(provider); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + symbol, + provider, + period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + /** + * Handle Signal Recieved ... + * + * @param signal: XSignal + */ + void HandleSignal(XSignal &signal) + { + // + // Validate Signal ... + if (!signal.IsValid()) + { + return; + } + + // + // Check Signal ... + bool isExecuted = false; + ENUM_X_SIGNAL_EXECUTION_RESULT signalExecutionResult; + bool canExecute = CheckSignal( + signal, + signalExecutionResult // + ); + if (canExecute) + { + // + HandleSignalVolume(signal); + isExecuted = Execute(signal); + } + + // + // Draw Signal Object ... + XCSignalObject *signalObj; + bool has = drawer.DrawSignal( + signal, + signalObj, + 4 // + ); + if (has) + { + mObjects.Add(signalObj); + } + } + + /** + * Handle Position Take Profit ... + * + * @param deal: XDeal instance reference ... + */ + void HandleTP(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XTRADE_FINAL_TP; + + // + // Save Trade ... + SaveWin(trades[idx]); + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "TP: " + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Config ... + + // + int configIdx = FindSymbolConfigurationIndex( + trades[idx].signal.symbol, + trades[idx].signal.period // + ); + isExists = IsValidIndex(configIdx); + if (isExists) + { + // + symbolTradeConfigs[configIdx].profits += 1; + symbolTradeConfigs[configIdx].managedTPs += 1; + symbolTradeConfigs[configIdx].managedProfits += trades[idx].profit; + } + + // + RemoveTrade(idx); + } + + /** + * Handle Position Stop Loss ... + * + * @param deal: XDeal instance reference ... + */ + void HandleSL(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XTRADE_FINAL_SL; + + // + // Save Trade ... + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "SL: " + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + bool isInProfit = trades[idx].profit > 0; + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + // Handle Symbol Config ... + + // + int configIdx = FindSymbolConfigurationIndex( + trades[idx].signal.symbol, + trades[idx].signal.period // + ); + isExists = IsValidIndex(configIdx); + if (isExists) + { + // + if (isInProfit) + { + // + symbolTradeConfigs[configIdx].profits += 1; + symbolTradeConfigs[configIdx].managedTPs += 1; + } + else + { + // + symbolTradeConfigs[configIdx].losses += 1; + symbolTradeConfigs[configIdx].managedSLs += 1; + } + + // + symbolTradeConfigs[configIdx].managedProfits += trades[idx].profit; + } + + // + RemoveTrade(idx); + } + + /** + * Handle Position Force Close ... + * + * @param deal: XDeal instance reference ... + */ + void HandleForceClose(const XPosition &position) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + position.ticket // + ); + if (!isExists) + { + return; + } + + // + bool isInProfit = position.profit > 0; + + // + // Apply Required Data ... + trades[idx].swap = position.swap; + trades[idx].profit = position.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].commission = position.commission; + trades[idx].finalize = isInProfit + ? XTRADE_FINAL_CLOSE_IN_PROFIT + : XTRADE_FINAL_CLOSE_IN_LOSE; + + // + // Save Trade ... + SaveTrade(trades[idx]); + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + // Handle Balance Reporting ... + string prefix = "Force Close " + + (isInProfit + ? "Profit" + : "Loss") + + ": " + + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Config ... + + // + int configIdx = FindSymbolConfigurationIndex( + trades[idx].signal.symbol, + trades[idx].signal.period // + ); + isExists = IsValidIndex(configIdx); + if (isExists) + { + // + if (isInProfit) + { + // + symbolTradeConfigs[configIdx].profits += 1; + symbolTradeConfigs[configIdx].managedTPs += 1; + } + else + { + // + symbolTradeConfigs[configIdx].losses += 1; + symbolTradeConfigs[configIdx].managedSLs += 1; + } + + // + symbolTradeConfigs[configIdx].managedProfits += trades[idx].profit; + } + + // + RemoveTrade(idx); + } + + /** + * Handle All Symbols Config Force Close At Time ... + * + * @return ( bool ) + */ + bool HandleForceCloseAtTime() + { + // + bool result = false; + + // + // Check Symbol Config Exists ... + result = HasChild(symbolTradeConfigs); + if (!result) + { + return result; + } + + // + result = false; + int count = ArraySize(symbolTradeConfigs); + for (int i = 0; i < count; i++) + { + // + // Check Can Force Closed At ... + bool has = IsSpecifiedValid(symbolTradeConfigs[i].closeAllOpenTradesAt); + if (!has) + { + continue; + } + + // + // Parse Date ... + datetime forceCloseTime = ParseDateTimeFromTimeString(symbolTradeConfigs[i].closeAllOpenTradesAt); + has = IsTimeInRange( + TimeCurrent(), + forceCloseTime // + ) && + !symbolTradeConfigs[i].isForceCloseAtTime; + if (!has) + { + continue; + } + + // + // Selecting Positions ... + XTradeInfo iTrades[]; + int iTradesCount = FillSymbolConfigurationTrades( + symbolTradeConfigs[i], + iTrades // + ); + has = IsValidSize(iTradesCount); + if (!has) + { + // + SpecifiedClean(iTrades); + continue; + } + + // + // Converts Trades to Positions ... + XPosition iPositions[]; + int iPositionsCount = ToXPositions( + iTrades, + iPositions // + ); + has = IsValidSize(iPositionsCount); + if (!has) + { + // + SpecifiedClean(iTrades); + SpecifiedClean(iPositions); + continue; + } + + // + // Do Force Closing ... + has = HandleForceCloseTrades(iPositions); + if (has && !result) + { + result = true; + } + + // + // Cleanup Resources ... + SpecifiedClean(iTrades); + SpecifiedClean(iPositions); + } + + // + return result; + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ULONG ... + * @param profit: double ... + * @param comment: string ... + */ + void HandlePartiallyClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + // Handle Balance Reporting ... + string prefix = "Partially Closed: " + ToXString(ticket); + + // + // Handle Balance Reporting ... + HandleReportBalance(prefix); + } + + /** + * Handle Guard Events ... + * + * @param action: ENUM_X_GUARD_ACTIONS + * @param positions: XPosition[] + */ + void HandleGuardEvent( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // + ) + { + } + + // + // Protected ... + protected: + // + // Tools ... + + // + string GetTradeFilePath(XTradeInfo &trade) + { + // + string fileName = trade.GetFileName(); + + // + return GetTradeFilePath(fileName); + } + + // + string GetTradeFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Trades" + "\\" + fileName); + + // + return result; + } + + // + string GetSignalFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Signals" + "\\" + fileName); + + // + return result; + } + + // + string GetWinsFilePath(XTradeInfo &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToXString(trade.signal.period) + "_wins"); + + // + return result; + } + + // + string GetLostsFilePath(XTradeInfo &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToXString(trade.signal.period) + "_losts"); + + // + return result; + } + + // + string GetRestrictionsFilePath(string symbol) + { + // + string result = NULL; + + // + if (!IsValid(symbol)) + { + return result; + } + + // + result = collector + .GetFilePath("Restrictions" + "\\" + symbol); + + // + return result; + } + + // + void HandleReportBalance(string prefix = NULL) + { + // + if (!reportAfterTradesBalance) + { + return; + } + + // + double balance = trader.mAccount.GetBalance(); + string currency = trader.mAccount.GetCurrency(); + + // + string message = + (IsValid(prefix) + ? prefix + " | " + : "") + + "Account Balance: " + ToXString(balance) + currency; + alert.SendAlert(message); + } + + // + void HandleReportProtector(string message = NULL) + { + // + if (!reportProtector) + { + return; + } + + // + alert.SendAlert(message); + } + + /** + * Handle All Exists Symbol Configurations Restrictions ... + */ + void HandleRestrictions() + { + // + // Count Symbol Configurations ... + int count = ArraySize(symbolTradeConfigs); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + // Handle Restrictions ... + datetime cTime = TimeCurrent(); + bool isNewDay = timeTracker.IsNewDay(); + for (int i = 0; i < count; i++) + { + // + // Reset Force Close At Time ... + if (isNewDay) + { + symbolTradeConfigs[i].isForceCloseAtTime = false; + } + + // + // Handle Restrictions ... + symbolTradeConfigs[i].HandleRestrictions(cTime); + } + } + + /** + * Apply Signal Volume ... + * + * @param signal: XSignal + */ + void HandleSignalVolume(XSignal &signal) + { + // + // Validate ... + if (!signal.IsValid()) + { + return; + } + + // + // Handle Volume Management ... + double iVolume = volume.CalculateVolume(signal); + bool has = iVolume > X_MIN_VOLUME && + iVolume != signal.volume; + if (has) + { + signal.volume = iVolume; + } + + // + // Here we Can Implement Custom Signalling Volume Management + // based on Different Symbol Configurations ... + } + + /** + * Handle Force Close Trades ... + */ + bool HandleForceCloseTrades( + XPosition &positions[] // + ) + { + // + bool result = false; + + // + result = HasChild(positions); + if (!result) + { + return result; + } + + // + string prefix = "Protector: "; + string comment = "Force Close ..."; + + // + int count = ArraySize(positions); + for (int i = 0; i < count; i++) + { + HandleForceClose(positions[i]); + } + + // + result = IsValidSize(count); + if (result) + { + // + string message = prefix + "Force Close (" + ToXString(count) + ") Trades at Specified Time ..."; + HandleReportProtector(message); + } + + // + return result; + } + + /** + * Check For Guards ... + * + * @param dest: XGuard[] + */ + int CheckForGuard(XGuard &dest[]) + { + // + int result = 0; + + // + // Cleanup Dest ... + SpecifiedClean(dest); + + // + // Check For Guards ... + if (checkForGuardEventListener != NULL) + { + result = checkForGuardEventListener(dest); + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Save Trades ... + bool SaveTrade( + XTradeInfo &trade, + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + bool result = false; + + // + if (!mSaveTrades) + { + return result; + } + + // + string filePath = GetTradeFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = trade.ToString( + includeSummary, + includeSignal, + includeConditions // + ); + + // + result = collector.Save( + filePath, + content // + ); + + // + return result; + } + + // + // Save Signals ... + bool SaveSignal(XSignal &signal) + { + // + bool result = false; + + // + // Check Signal Save is Enabled ... + if (!mSaveSignals) + { + return result; + } + + // + // Check Signal Validation ... + if (!signal.IsValid()) + { + return result; + } + + // + // Retrieve Signal File Name ... + string signalFileName = signal.GetFileName(); + result = IsValid(signalFileName); + if (!result) + { + return result; + } + + // + // Retriev and Validate File Name ... + string filePath = GetSignalFilePath(signalFileName); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Generate Content ... + string content = ""; + content += + ToXString("----------------") + "\n" + + ToXString("Signal: ") + "\n" + + ToXString("----------------") + "\n" + + signal.ToString() + "\n"; + content += + ToXString("----------------") + "\n" + + ToXString("Conditions: ") + "\n" + + ToXString("----------------") + "\n" + + signal.conditions + "\n"; + + // + // Save Content to File ... + result = collector.Save( + filePath, + content // + ); + + // + // Return Result ... + return result; + } + + // + bool SaveWin(XTradeInfo &trade) + { + // + bool result = false; + + // + if (!mSaveWins) + { + return result; + } + + // + string filePath = GetWinsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveLost(XTradeInfo &trade) + { + // + bool result = false; + + // + if (!mSaveLosts) + { + return result; + } + + // + string filePath = GetLostsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + CArrayObj mObjects; + + // + bool allowTrade; + bool allowLongs; + bool allowShorts; + + // + bool mSaveWins; + bool mSaveLosts; + bool mSaveTrades; + bool mSaveSignals; + bool mSaveRestrictions; + + // + bool reportTrades; + bool reportSignals; + bool reportProtector; + bool reportRestrictions; + bool reportAfterTradesBalance; + + // + XTradeInfo trades[]; + XSymbolTradeConfig symbolTradeConfigs[]; + + /** + * Find Executed Trade by Providing Position Ticket ... + * + * @param index: int reference, holding founded item index ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + ticket > 0 && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XTradeInfo iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.IsExecuted() && + iTrade.positionID == ticket; + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Trade Item By Signal ... + * + * @param index: int reference, holding founded item index ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + signal.IsValid() && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XTradeInfo iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.signal.IsSameAs(signal); + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove a Trade From List ... + * + * @param index: int ... + */ + void RemoveTrade(int index) + { + // + bool has = + HasChild(trades) && + IsValidIndex(index) && + index < ArraySize(trades); + if (!has) + { + return; + } + + // + ArrayRemove( + trades, + index, + 1 // + ); + } + + // + void AddOrUpdateSymbolConfiguration(XSymbolTradeConfig &config) + { + // + // Check Validation ... + bool has = config.IsValid(); + if (!has) + { + return; + } + + // + // Check Index ... + int idx = FindSymbolConfigurationIndex(config); + has = IsValidIndex(idx); + if (has) + { + // + // Update Exists ... + symbolTradeConfigs[idx] = config; + } + else + { + // + // Add New ... + AddRef( + config, + symbolTradeConfigs // + ); + } + } + + // + void AddDefaultSymbolConfiguration() + { + // + // Define new Configuration ... + XSymbolTradeConfig iConfig; + + // + // Check Initialization ... + bool has = iConfig.Init( + _Symbol, + _Period // + ); + + // + // Add Or Update ... + if (has) + { + AddOrUpdateSymbolConfiguration(iConfig); + } + + // + // Clean Resources ... + iConfig.Clean(); + } + + // + int FindSymbolConfigurationIndex(XSymbolTradeConfig &config) + { + // + int result = -1; + + // + if (!config.IsValid() || !SpecifiedHasChild(symbolTradeConfigs)) + { + return result; + } + + // + int count = ArraySize(symbolTradeConfigs); + for (int i = 0; i < count; i++) + { + // + if (symbolTradeConfigs[i].IsSame(config)) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + int FillSymbolConfigurationTrades( + XSymbolTradeConfig &config, + XTradeInfo &dest[] // + ) + { + // + int result = 0; + + // + SpecifiedClean(dest); + + // + // Check Trades ... + int count = ArraySize(trades); + if (!IsValidSize(count)) + { + return result; + } + + // + // Validate Config ... + if (!config.IsValid()) + { + return result; + } + + // + // Find Config ... + int idx = FindSymbolConfigurationIndex(config); + if (!IsValidIndex(idx)) + { + return result; + } + + // + bool has = false; + string symbol = symbolTradeConfigs[idx].symbol; + ENUM_TIMEFRAMES period = symbolTradeConfigs[idx].period; + for (int i = 0; i < count; i++) + { + // + has = + trades[i].signal.symbol == symbol && + trades[i].signal.period == period && + trades[i].positionID > 0; + if (!has) + { + continue; + } + + // + AddRef( + trades[i], + dest // + ); + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + int FindSymbolConfigurationIndex( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + int result = -1; + + // + // Validate Args ... + if ( + !IsSpecifiedValid(symbol) || + !IsSpecifiedValid(period) || + !HasChild(symbolTradeConfigs)) + { + return result; + } + + // + int count = ArraySize(symbolTradeConfigs); + for (int i = 0; i < count; i++) + { + // + if (symbolTradeConfigs[i].symbol == symbol && + symbolTradeConfigs[i].period == period) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + // Tools ... + + // + int ToXPositions( + XTradeInfo &source[], + XPosition &dest[] // + ) + { + // + int result = 0; + + // + SpecifiedClean(dest); + + // + int count = ArraySize(source); + bool has = IsValidSize(count); + if (!has) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition; + has = trader.GetPosition( + source[i].positionID, + iPosition); + if (has) + { + // + AddRef( + iPosition, + dest // + ); + } + + // + iPosition.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + string EscapeString(string value) + { + // + string result = value; + + // + if (!IsSpecifiedValid(value)) + { + return result; + } + + // + StringReplace( + result, + "[", + "" // + ); + + // + StringReplace( + result, + "]", + "" // + ); + + // + StringReplace( + result, + "|", + "" // + ); + + // + result = Trim(result); + + // + return result; + } +}; \ No newline at end of file diff --git a/BKPS/14040626/Classes/x-saherelm.x-trade.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-trade.class.mq5 new file mode 100644 index 0000000..4fd81d0 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-trade.class.mq5 @@ -0,0 +1,3899 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCTrade +// Description: provides all Trade requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-account.class.mq5" +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +// +// Overrides ... + +// +// XCTrade Base Class ... +class XCTradeBase : public CTrade +{ + public: + // + // Modify Specific Position, by Specific Comment ... + bool PositionModify( + const string symbol, // Symbol + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!SelectPosition(symbol)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + bool PositionModify( + const ulong ticket, // Position Ticket + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.position = ticket; + m_request.symbol = PositionGetString(POSITION_SYMBOL); + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + + // + // Close Specific Position, by Specific Comment ... + bool PositionClose( + const string symbol, // Symbol + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + bool partial_close = false; + int retry_count = 10; + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + do + { + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specify Comment ... + m_request.comment = comment; + + // + // check volume + double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + if (m_request.volume > max_volume) + { + // + m_request.volume = max_volume; + partial_close = true; + } + else + { + partial_close = false; + } + + // + // hedging? just send order + if (IsHedging()) + { + return (OrderSend(m_request, m_result)); + } + + // + // order send + if (!OrderSend(m_request, m_result)) + { + // + if (--retry_count != 0) + { + continue; + } + + // + if (retcode == TRADE_RETCODE_DONE_PARTIAL) + { + m_result.retcode = retcode; + } + + // + return (false); + } + + // + //--- WARNING. If position volume exceeds the maximum volume allowed for deal, + //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, + //--- but partially. It is decreased by the maximum volume allowed for deal. + if (m_async_mode) + { + break; + } + + // + retcode = TRADE_RETCODE_DONE_PARTIAL; + if (partial_close) + { + Sleep(1000); + } + } while (partial_close); + + // + // succeed + return (true); + } + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } + + // + // Partial Close Specific Position, by Specific Comment ... + bool PositionClosePartial( + const string symbol, // Symbol + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // hedging? just send order + return (OrderSend(m_request, m_result)); + } + bool PositionClosePartial( + const ulong ticket, // Position Ticket + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } +}; + +// +// Implementation ... + +// +// a Class For Manage Trades and Handle Trading Actions ... +class XCTrade : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAccount *mAccount; // Account Info Provider + + // + // Constructors ... + void XCTrade( + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + double maxAllowedSpread = 0, // Max Allowed Spred for Opening Trades + int maxAllowedPositions = 0, // Max Allowed Positions + double maxAllowedDrawdownFactor = 0 // Max Allowed Drawdown Factor + ) + { + // + // Setting Props ... + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mMaxAllowedSpread = maxAllowedSpread; + mMaxAllowedPositions = maxAllowedPositions; + mMaxAllowedDrawdownFactor = maxAllowedDrawdownFactor; + + // + mAccount = new XCAccount(); + + // + // Instance Base Trader Class ... + mTrader = new XCTradeBase(); + + // + // Configuring Base Trader Class ... + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + // OnTrade Context ... + + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + } + + // + // Deconstructor ... + ~XCTrade() + { + // + // Remove Pointer ... + delete mTrader; + delete mAccount; + + // + ZeroMemory(mTrader); + ZeroMemory(mAccount); + + // + Clean(mOnModifyEventHandlers); + Clean(mStopLossEventHandlers); + Clean(mTakeProfitEventHandlers); + Clean(mOnForceCloseEventHandlers); + Clean(mDealsChangedEventHandlers); + Clean(mOrdersChangedEventHandlers); + Clean(mOnPartialCloseEventHandlers); + Clean(mPositionsChangedEventHandlers); + Clean(mTradeStateChangedEventHandlers); + } + + // + // Props ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mSlippage; + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + double GetMaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + // + int GetMaxAllowedPositions() + { + return mMaxAllowedPositions; + } + + // + void SetMaxAllowedPositions(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedPositions = value; + } + + // + double GetMaxAllowedDrawdownFactor() + { + return mMaxAllowedDrawdownFactor; + } + + // + // Add Event Listeners ... + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + // Add New Orders Changed Event Handler ... + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + // Add New Positions Changed Event Handler ... + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + // Functions ... + + // + // Handlers ... + + // + // Process On Trade Requirement ... + // this Only Used when we Have to Proccess OnTrade Event in EA(s) ... + void HandleOnTradeEvent( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + result.Clean(); + + // + if (mScanStarted) + { + // + ProcessOnTradeContext(result); + } + else + { + // + // Init Trade Context ... + InitOnTradeContext(); + + // + return; + } + + // + // Here we Can Check the Start ... + bool isValid = + // + result.IsValid() && + // + !result.hasNewDeal && + !result.hasNewOrder && + !result.hasNewPosition && + !result.hasNewHistoryOrder + // + ; + if (!isValid) + { + return; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(result); + + // + // Deals ... + if (result.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(result.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + int dealsCount = GetDeals(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // Orders ... + if (result.hasNewOrder || result.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(result.newOrders + result.newHistoryOrders); + } + + // + // Positions ... + if (result.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(result.newPositions); + } + } + + // + // This Must be Called Every time OnTrade Event Happening ... + // this Used for Implementing Custom Senarios ... + XOnTradeHandlerState HandleOnTrade() + { + // + // Handle OnTrade Event ... + XOnTradeHandlerState state; + HandleOnTradeEvent(state); + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return state; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(state.newPositions); + } + + // + return state; + } + + // + // Trade Actions ... + + // + // Main ... + + // + // Policies ... + + // + // Check Acocunt Balance is Allow new Trades or not ... + bool CheckEquityForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedDrawdownFactor <= 0) + { + // + result = true; + return result; + } + + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double selectedBalance = MathMax(equity, balance) - MathMin(equity, balance); + + // + double maxAllowedBalanceDrawDown = GetMaxAllowedEquity(); + + // + result = equity > balance || + (equity <= balance && + selectedBalance <= maxAllowedBalanceDrawDown); + + // + return result; + } + + // + // Check Max Allowed Positions Policy for Trade ... + bool CheckPositionsForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedPositions <= 0) + { + // + result = true; + return result; + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + if (positionsCount <= 0) + { + // + result = true; + return result; + } + + // + result = positionsCount < mMaxAllowedPositions; + + // + return result; + } + + // + // Check Spread is Ok for Executing Specific Signal ... + bool CheckSpreadForSignalExecution(XSignal &mSignal) + { + // + bool result = false; + + // + bool isSpreadCheckEnable = mMaxAllowedSpread > 0; + if (!isSpreadCheckEnable) + { + result = true; + } + else + { + // + // Retrieve Signal Spread ... + double spread = GetSpread(mSignal.symbol); + result = spread <= mMaxAllowedSpread; + } + + // + return result; + } + + // + // Check Account Policy ... + bool CheckAccountPolicy( + XSignal &mSignal, // For Executing Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state // State Holder + ) + { + // + bool result = false; + + // + // Check Positions For Trade ... + result = CheckPositionsForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + + // + // Check Equity For Trade ... + result = CheckEquityForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + + // + // Check Spread for Trade ... + result = CheckSpreadForSignalExecution(mSignal); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_SPREAD; + return result; + } + + // + return result; + } + + // + // Execute a Signal ... + bool ExecuteSignal( + XSignal &mSignal, // Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + bool result = false; + state = X_SIGNAL_EXECUTION_UNKNOWN; + + // + double currentEntry = GetEntry( + mSignal.symbol, + mSignal.type + // + ); + bool isLong = IsLong(mSignal.type); + + // + if (!mSignal.IsValid()) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + // Prepare Signal Comment ... + string mSComment = mSignal.GenerateComment(); + if (!Contains(mSComment, mSignal.comment)) + { + mSignal.comment += mSComment; + } + + // + // Handle Market Execution ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + // + // Do Apply Policies here ... + bool hasPolicy = !checkPolicies + ? true + : CheckAccountPolicy(mSignal, state); + if (!hasPolicy) + { + result = false; + } + else + { + // + if (isLong) + { + // + result = Buy( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + mSignal.comment + // + ); + } + else + { + // + result = Sell( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + mSignal.comment + // + ); + } + } + } + // + // Handle Stop Execution ... + else if (mSignal.mode == X_ORDER_MODE_STOP) + { + + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? mSignal.entry > currentEntry + : mSignal.entry < currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyStop( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + else + { + // + result = SellStop( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + } + // + // Handle Limit Execution ... + else if (mSignal.mode == X_ORDER_MODE_LIMIT) + { + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? mSignal.entry < currentEntry + : mSignal.entry > currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyLimit( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + else + { + // + result = SellLimit( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + } + + // + // Handle Ticket ... + if (result) + { + // + state = X_SIGNAL_EXECUTION_SUCCEED; + + // + ulong ticket; + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + ticket = GetLastOpenPositionTicket(); + } + else + { + ticket = GetLastPlacedOrderTicket(); + } + + // + mSignal.positionId = ticket; + + // + // Handle Store XPositionInfo ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + // + // TODO: Implement this ... + } + } + + // + return result; + } + + // + // Execute a Collection Of Signals ... + int ExecuteSignals( + XSignal &signals[], // Collection of Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration, + checkPolicies + // + ); + + // + if (isExecuted) + { + result++; + } + } + + // + return result; + } + + // + int ExecuteSpecifiedSignals( + XSignal &signals[], // Collection of Signal for Execution + XSignal ¬Executeds[], // Not Executed Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + Clean(notExecuteds); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration + // + ); + + // + if (isExecuted) + { + result++; + } + else + { + // + AddRef( + signals[i], + notExecuteds // + ); + } + } + + // + return result; + } + + // + // Regular Trade Actions ... + + // + // Buy ... + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Sell ... + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Check a Position is Exists Open or not ... + bool IsOpen( + ulong ticket // Specified Position Ticket + ) + { + // + bool result = false; + + // + result = mPositionInfo + .SelectByTicket(ticket); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = NULL // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + XPosition position; + result = + GetPosition( + ticket, + position // + ) && + (tp >= 0 || sl >= 0); + if (!result) + { + return result; + } + + // + // Use Position Comment when there isn't new One ... + if (!IsValid(comment) == 0) + { + // + // if there isn't provided Comment + // Use Position Comment for default ... + comment = "Modify " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment + // + ); + if (result) + { + // + NotifyModifyEvent( + ticket, + position.profit, + comment // + ); + } + + // + return result; + } + + // + // Close Position By Ticket ... + bool Close( + ulong ticket, // Position Ticket + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + // Check Position Open ... + XPosition position; + result = GetPosition( + ticket, + position // + ); + if (!result) + { + return result; + } + + // + // Use Default Position Comment if it's Not Provided ... + if (!IsValid(comment)) + { + comment = "Close " + GetPositionComment(ticket); + } + + // + // Close Position By Specific Comment ... + result = mTrader.PositionClose( + ticket, + mSlippage, + comment + // + ); + if (result) + { + // + NotifyForceCloseEvent( + ticket, + position, + comment // + ); + } + + // + return result; + } + + // + // Close Specified Positions ... + int Close( + string comment = NULL, // Close Position By Specific Comment + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close a Collection of Positions ... + int Close( + XPosition &positions[], // Collection of Positions + string comment = NULL // 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 GetPositionByIndex( + 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/14040626/Classes/x-saherelm.x-volume.class.mq5 b/BKPS/14040626/Classes/x-saherelm.x-volume.class.mq5 new file mode 100644 index 0000000..09720c3 --- /dev/null +++ b/BKPS/14040626/Classes/x-saherelm.x-volume.class.mq5 @@ -0,0 +1,792 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCVolume +// Description: provides all Requirements for Volume Managing ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Template Variables of Inputs for Using ... +// input group "Volume"; +// input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_STATIC; // Volume Applying Type +// input double eaStaticVoluem = X_MIN_VOLUME; // Static Volume +// input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +// input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +// input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +// input double eaConstantPercent = 0.0; // Constant Percent of Balance Per Trade +// input double eaConstantBalance = 0.0; // Constant Balance for Calculations +// XCVolume *eaVolume; +// eaVolume = new XCVolume(); +// bool result = eaVolume.Init( +// eaVolumeSelect, +// eaStaticVoluem, +// eaDynamicVolumeStepBalance, +// eaDynamicVolumeStepVolume, +// eaConstantRiskBalance, +// eaConstantPercent, +// eaConstantBalance // +// ); +// if (!result) { +// return INIT_FAILED; +// } + +// +// Imports ... +#include "../Classes/x-saherelm.x-account.class.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... +#define X_MIN_VOLUME 0.01 + +// +enum ENUM_X_VOLUME_SELECT_TYPE +{ + X_VOLUME_NONE, // None + X_VOLUME_STATIC, // Static Volume + X_VOLUME_CURRENT, // Current Balance + X_VOLUME_EQUITY, // Current Equity + X_VOLUME_CONSTANT // Constant Value +}; + +// +bool IsValid(ENUM_X_VOLUME_SELECT_TYPE value) +{ + // + bool result = false; + + // + result = value != X_VOLUME_NONE; + + // + return result; +} + +// +string ToString(ENUM_X_VOLUME_SELECT_TYPE value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +// Implementation ... +class XCVolume : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAccount *account; + + // + // Constructor ... + XCVolume() + { + // + account = new XCAccount(); + + // + Default(); + } + + // + // Deconstructor ... + ~XCVolume() + { + // + ZeroMemory(account); + } + + // + bool Init( + ENUM_X_VOLUME_SELECT_TYPE _SelectType, + double _StaticVolume, + double _DynamicVolumeStepBalance, + double _DynamicVolumeStepVolume, + double _ConstantRiskBalance, + double _ConstantPercent, + double _ConstantBalance // + ) + { + // + bool result = false; + + // + mVolumeType = _SelectType; + mStaticVolume = _StaticVolume; + mConstantPercent = _ConstantPercent; + mConstantBalance = _ConstantBalance; + mConstantRiskBalance = _ConstantRiskBalance; + mDynamicVolumeStepVolume = _DynamicVolumeStepVolume; + mDynamicVolumeStepBalance = _DynamicVolumeStepBalance; + + // + result = + // + CanUseStaticVolume() || + CanUseDynamicVolume() || + CanUseConstantRiskBalance() || + CanUseConstantBalancePercent() + // + ; + + // + return result; + } + + // + // Prperties ... + + /** + * Get Volume Calculating Method ... + * + * @return (ENUM_X_VOLUME_SELECT_TYPE) + */ + ENUM_X_VOLUME_SELECT_TYPE VolumeType() + { + return mVolumeType; + } + + /** + * Set Volume Calculating Method ... + * + * @param value: ENUM_X_VOLUME_SELECT_TYPE member ... + */ + void VolumeType(ENUM_X_VOLUME_SELECT_TYPE value) + { + mVolumeType = value; + } + + /** + * Get Static Volume ... + * + * @return ( double ) + */ + double StaticVolume() + { + return mStaticVolume; + } + + /** + * Set Static Volume ... + * + * @param value: double + */ + void StaticVolume(double value) + { + // + value = NormalizeDouble(value, 0.01, 1); + + // + mStaticVolume = value; + } + + /** + * Get Dynamic Volume Step Balance ... + * used to Calculate Final Lottage ... + * + * @return ( double ) + */ + double DynamicVolumeStepBalance() + { + return mDynamicVolumeStepBalance; + } + + /** + * Set Dynamic Volume Step Balance ... + * used to Calculate Final Lottage ... + * + * @param value: Argument 1 + */ + void DynamicVolumeStepBalance(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mDynamicVolumeStepBalance = value; + } + + /** + * Get Dynamic Volume Step Volume ... + * used to Calculate Final Lottage ... + * how much increase Final Volume based oBalance Step ... + * + * @return ( double ) + */ + double DynamicVolumeStepVolume() + { + return mDynamicVolumeStepVolume; + } + + /** + * Get Dynamic Volume Step Volume ... + * used to Calculate Final Lottage ... + * how much increase Final Volume based oBalance Step ... + * + * @param value: double + */ + void DynamicVolumeStepVolume(double value) + { + // + value = NormalizeDouble(value, 0.01, 0.1); + + // + mDynamicVolumeStepVolume = value; + } + + /** + * Get Constant Balance Use for Dyamic Volume Calculation ... + * + * @return ( double ) + */ + double ConstantBalance() + { + return mConstantBalance; + } + + /** + * Set Constant Balance Use for Dyamic Volume Calculation ... + * + * @param value: Argument 1 + */ + void ConstantBalance(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mConstantBalance = value; + } + + /** + * Get Constant Risk Value Based on Account Currency ... + * + * @return ( double ) + */ + double ConstantRiskBalance() + { + return mConstantRiskBalance; + } + + /** + * Get Constant Risk Value Based on Account Currency ... + * + * @param value: double + */ + void ConstantRiskBalance(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mConstantRiskBalance = value; + } + + /** + * Get Constant Percent Based On Selected Balance ... + * + * @return ( double ) + */ + double ConstantPercent() + { + return mConstantPercent; + } + + /** + * Set Constant Percent Based On Selected Balance ... + * + * @param value: double ... + */ + void ConstantPercent(double value) + { + // + value = NormalizeDouble(value, 0, 100); + + // + mConstantPercent = value; + } + + // + // Tools ... + + /** + * Retrieve Balance based on Provided Volume Type ... + * + * @return ( double ) + */ + double GetBalance() + { + // + double result = 0; + + // + if (!IsValid(mVolumeType)) + { + return result; + } + + // + if (mConstantBalance > 0 && + mVolumeType == X_VOLUME_CONSTANT) + { + result = mConstantBalance; + } + else if (mVolumeType == X_VOLUME_CURRENT) + { + result = account.GetBalance(); + } + else if (mVolumeType == X_VOLUME_EQUITY) + { + result = account.GetEquity(); + } + + // + return result; + } + + /** + * Retrieve Balance based on Provided Volume Type ... + * + * @return ( double ) + */ + double GetBalance(ENUM_X_VOLUME_SELECT_TYPE type) + { + // + double result = 0; + + // + if (!IsValid(type)) + { + return result; + } + + // + if (mConstantBalance > 0 && + type == X_VOLUME_CONSTANT) + { + result = mConstantBalance; + } + else if (type == X_VOLUME_CURRENT) + { + result = account.GetBalance(); + } + else if (type == X_VOLUME_EQUITY) + { + result = account.GetEquity(); + } + + // + return result; + } + + /** + * Calculate Volume Based On Given Configuration ... + * + * @param symbol: string, Trading Symbol ... + * @param entry: double, Entry Price ... + * @param sl: double, Stop Loss Price ... + * + * @return ( double ) + */ + double CalculateVolume( + string symbol, + double entry, + double sl // + ) + { + // + double result = X_MIN_VOLUME; + + // + bool has = false; + + // + // Validate Args ... + has = + sl > 0 && + entry > 0 && + IsValid(symbol); + if (!has) + { + return result; + } + + // + // Retrieve Balance Type ... + double balance = GetBalance(); + double points = GetPoints(symbol); + double riskPrice = MathAbs(entry - sl); + double riskInPoints = riskPrice / points; + + // + has = CanUseStaticVolume(); + if (has) + { + result = mStaticVolume; + } + + // + has = CanUseDynamicVolume(); + if (has) + { + // + double multiplier = balance / mDynamicVolumeStepBalance; + if (multiplier < 0) + { + multiplier = 1; + } + + // + result = multiplier * mDynamicVolumeStepVolume; + } + + // + has = CanUseConstantRiskBalance(); + if (has) + { + // + result = account.CalculateVolume( + symbol, + mConstantRiskBalance, + riskInPoints // + ); + } + + // + has = CanUseConstantBalancePercent(); + if (has) + { + // + double riskAmountPerBalance = (mConstantPercent * balance) / 100; + + // + result = account.CalculateVolume( + symbol, + riskAmountPerBalance, + riskInPoints // + ); + } + + // + if (result < X_MIN_VOLUME) + { + result = X_MIN_VOLUME; + } + + // + // Normalize Volume ... + result = NormalizeVolume(result, symbol); + + // + return result; + } + + /** + * Calculate Volume Based On Given Configuration ... + * + * @param signal: XSignal instance reference, provided required Data ... + * + * @return ( double ) + */ + double CalculateVolume(XSignal &signal) + { + // + double result = X_MIN_VOLUME; + + // + if (!signal.IsValid()) + { + return result; + } + + // + result = CalculateVolume( + signal.symbol, + signal.entry, + signal.sl // + ); + + // + return result; + } + + /** + * Calculate Specified Percent of Selected Balance for Volume ... + * + * @param percent: double, percent of Balance Risking ... + * @param symbol: string, Trading Symbol ... + * @param entry: double, Entry Price ... + * @param sl: double Stop Loss Price ... + * + * @return ( double ) + */ + double CalculateVolume( + ENUM_X_VOLUME_SELECT_TYPE selectType, + double percent, + string symbol, + double entry, + double sl // + ) + { + // + double result = X_MIN_VOLUME; + + // + bool has = false; + + // + // Validate Args ... + has = + sl > 0 && + entry > 0 && + percent > 0 && + IsValid(symbol) && + IsValid(selectType) && + (selectType == X_VOLUME_EQUITY || + selectType == X_VOLUME_CURRENT); + if (!has) + { + return result; + } + + // + // Retrieve Balance Type ... + double points = GetPoints(symbol); + double riskPrice = MathAbs(entry - sl); + double balance = GetBalance(selectType); + double riskInPoints = riskPrice / points; + + // + double riskAmountPerBalance = (percent * balance) / 100; + + // + result = account.CalculateVolume( + symbol, + riskAmountPerBalance, + riskInPoints // + ); + + // + return result; + } + + // + // Protected ... + protected: + // + // Tools ... + + /** + * Set Default Props ... + */ + void Default() + { + // + VolumeType(X_VOLUME_STATIC); + StaticVolume(0.01); + + // + ConstantBalance(0); + ConstantPercent(0); + ConstantRiskBalance(0); + + // + DynamicVolumeStepBalance(0); + DynamicVolumeStepVolume(0.01); + } + + /** + * Check Configuration is Valid For Static Volume ... + * + * @return ( bool ) + */ + bool CanUseStaticVolume() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + // Static Volume ... + result = + // + mVolumeType == X_VOLUME_STATIC && + mStaticVolume > 0 && + // + mDynamicVolumeStepBalance == 0 && + // + mConstantBalance == 0 && + mConstantPercent == 0 && + mConstantRiskBalance == 0 + // + ; + + // + return result; + } + + /** + * Check Configuration is Valid For Dynamic Volume ... + * + * @return ( bool ) + */ + bool CanUseDynamicVolume() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + result = + // + (mVolumeType == X_VOLUME_CURRENT || + mVolumeType == X_VOLUME_EQUITY || + (mVolumeType == X_VOLUME_CONSTANT && + mConstantBalance > 0)) && + // + mDynamicVolumeStepBalance > 0 && + mDynamicVolumeStepVolume > 0 && + // + mStaticVolume == 0 && + mConstantPercent == 0 && + mConstantRiskBalance == 0 + // + ; + + // + return result; + } + + /** + * Check Configuration is Valid For Constant Risk Balance ... + * + * @return ( bool ) + */ + bool CanUseConstantRiskBalance() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + result = + // + (mVolumeType == X_VOLUME_CURRENT || + mVolumeType == X_VOLUME_EQUITY || + (mVolumeType == X_VOLUME_CONSTANT && + mConstantBalance > 0)) && + // + mConstantRiskBalance > 0 && + // + mStaticVolume == 0 && + mConstantPercent == 0 && + mDynamicVolumeStepBalance == 0 + // + ; + + // + return result; + } + + /** + * Check Configuration is Valid For Constant Risk Percent ... + * + * @return ( bool ) + */ + bool CanUseConstantBalancePercent() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + result = + // + (mVolumeType == X_VOLUME_CURRENT || + mVolumeType == X_VOLUME_EQUITY || + (mVolumeType == X_VOLUME_CONSTANT && + mConstantBalance > 0)) && + // + mConstantPercent > 0 && + // + mStaticVolume == 0 && + mConstantRiskBalance == 0 && + mDynamicVolumeStepBalance == 0 + // + ; + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + ENUM_X_VOLUME_SELECT_TYPE mVolumeType; // Balance Type ... + + // + // Static Volume ... + double mStaticVolume; // Static Volume ... + + // + double mDynamicVolumeStepBalance; // Step of Balance ... + double mDynamicVolumeStepVolume; // Step of Volume ... + + // + double mConstantBalance; // Constant Balance .... + double mConstantRiskBalance; // Constant Risk Balance ... + double mConstantPercent; // Constant Percent of Balance ... +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/BKP/backtester.temp.mq5 b/BKPS/14040626/Documents/BKP/backtester.temp.mq5 new file mode 100644 index 0000000..e01c1c0 --- /dev/null +++ b/BKPS/14040626/Documents/BKP/backtester.temp.mq5 @@ -0,0 +1,1484 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XBackTester +// Description: a Backtest Tools Strategy Tester +// +// 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 XBackTester" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-chart.helper.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Import Chart Objects ... +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Definitions ... + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XCTrade *eaTrader; // Trader of Expert Adviser ... +XCChartHelper *mChartHelper; // Chart Helper Class ... + +// +// Object Props ... + +// +string objSuffix; + +// +CButton btnBuy; +CButton btnSell; +CButton btnClose; +CButton btnCloseAll; + +// +CEdit lblPositionId; + +// +CButton *btnSelectedPosInfo; +CArrayObj selectedPosInfoArr; + +// +int btnCloseSizeX = 0; +int btnCloseSizeY = 0; +int btnCloseStartX = 0; +int btnCloseStartY = 0; +int lblPositionIdSizeX = 0; +int lblPositionIdSizeY = 0; +int lblPositionIdStartX = 0; +int lblPositionIdStartY = 0; + +// +ulong selectedPositionID = 0; + +// +// Position Arrays ... +CArrayObj posArray; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); +} + +// +// 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 // +) +{ +} + +// +// 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; + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XCTrade( + eaSlippage, + eaMagicNumber // + ); + + // + // Attach Event Handlers ... + eaTrader.AddOnDealsChangedEventHandler(OnDealsChanged); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnModifyPositionEventHandler(OnPositionModified); + eaTrader.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaTrader.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // TODO: Fix This ... + result = true; + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaAlert; +} + +// +// GUI Events ... + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + int subWindow = 0; + ulong chartId = ChartID(); + objSuffix = ShortName + "_"; + + // + // Initial Chart Class Instance ... + mChartHelper = new XCChartHelper(chartId); + + // + int startX = 5; + int startY = 25; + + // + int defaultGap = 5; + int defaultWidth = 100; + int defaultHeight = 30; + + // + // Buy ... + int btnBuyStartX = startX; + int btnBuySizeX = startX + defaultWidth; + int btnBuyStartY = startY; + int btnBuySizeY = startY + defaultHeight; + string btnBuyName = objSuffix + "BTN_BUY"; + result = btnBuy.Create( + chartId, + btnBuyName, + subWindow, + btnBuyStartX, + btnBuyStartY, + btnBuySizeX, + btnBuySizeY // + ); + if (result) + { + // + // Apply Buy Button Style ... + + // + btnBuy.Text("Buy"); + btnBuy.Color(clrYellow); + btnBuy.ColorBackground(clrGreen); + } + + // + // Sell ... + int btnSellStartX = btnBuyStartX + btnBuySizeX; + int btnSellSizeX = btnSellStartX + defaultWidth; + int btnSellStartY = btnBuyStartY; + int btnSellSizeY = btnBuySizeY; + string btnSellName = objSuffix + "BTN_SELL"; + result = btnSell.Create( + chartId, + btnSellName, + subWindow, + btnSellStartX, + btnSellStartY, + btnSellSizeX, + btnSellSizeY // + ); + if (result) + { + // + // Apply Sell Button Style ... + + // + btnSell.Text("Sell"); + btnSell.Color(clrYellow); + btnSell.ColorBackground(clrDarkRed); + } + + // + // LABEL Position ID ... + lblPositionIdStartX = btnBuyStartX; + lblPositionIdSizeX = lblPositionIdStartX + defaultWidth; + lblPositionIdStartY = btnSellSizeY + defaultGap; + lblPositionIdSizeY = lblPositionIdStartY + defaultHeight; + string lblPositionIdName = objSuffix + "LBL_POS_ID"; + result = lblPositionId.Create( + chartId, + lblPositionIdName, + subWindow, + lblPositionIdStartX, + lblPositionIdStartY, + lblPositionIdSizeX, + lblPositionIdSizeY // + ); + if (result) + { + // + // Apply Label Position ID Style ... + lblPositionId.ReadOnly(true); + lblPositionId.Text("Pos ID: "); + lblPositionId.Color(clrYellow); + lblPositionId.ColorBackground(clrDarkGray); + } + + // + // Close ... + btnCloseStartX = startX; + btnCloseSizeX = btnCloseStartX + defaultWidth; + btnCloseStartY = lblPositionIdSizeY + defaultGap; + btnCloseSizeY = lblPositionIdSizeY + defaultHeight; + string btnCloseName = objSuffix + "BTN_CLOSE"; + result = btnClose.Create( + chartId, + btnCloseName, + subWindow, + btnCloseStartX, + btnCloseStartY, + btnCloseSizeX, + btnCloseSizeY // + ); + if (result) + { + // + // Apply Close Button Style ... + + // + btnClose.Text("Close"); + btnClose.Color(clrYellow); + btnClose.ColorBackground(clrDarkOrange); + } + + // + // Close All ... + int btnCloseAllStartX = btnCloseSizeX + defaultGap; + int btnCloseAllSizeX = btnCloseAllStartX + defaultWidth; + int btnCloseAllStartY = lblPositionIdSizeY + defaultGap; + int btnCloseAllSizeY = lblPositionIdSizeY + defaultHeight; + string btnCloseAllName = objSuffix + "BTN_CLOSE_ALL"; + result = btnCloseAll.Create( + chartId, + btnCloseAllName, + subWindow, + btnCloseAllStartX, + btnCloseAllStartY, + btnCloseAllSizeX, + btnCloseAllSizeY // + ); + if (result) + { + // + // Apply Close Button Style ... + + // + btnCloseAll.Text("Close All"); + btnCloseAll.Color(clrYellow); + btnCloseAll.ColorBackground(clrDarkRed); + } + + // + UpdateGUIState(); + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + UpdateGUIState(); + + // + // Buy Button Pressed ... + if (btnBuy.Pressed()) + { + // + HandleBuyTrade(); + btnBuy.Pressed(false); + } + + // + // Sell Button Pressed ... + if (btnSell.Pressed()) + { + // + HandleSellTrade(); + btnSell.Pressed(false); + } + + // + // Close Button Pressed ... + if (btnClose.Pressed()) + { + // + if (btnClose.IsEnabled()) + { + // + if (selectedPositionID > 0) + { + HandleCloseTrade(selectedPositionID); + } + } + + // + btnClose.Pressed(false); + } + + // + // Close All Button Pressed ... + if (btnCloseAll.Pressed()) + { + // + if (btnCloseAll.IsEnabled()) + { + HandleCloseTrade(0); + } + + // + btnCloseAll.Pressed(false); + } + + // + // Check Show Hide Selected Position Info ... + if (btnSelectedPosInfo != NULL) + { + // + if (btnSelectedPosInfo.Pressed()) + { + // + // Check Enable ... + if (btnSelectedPosInfo.IsEnabled()) + { + // + // Handle Toggle Show/Hide lblSelectedPositionInfo ... + CEdit *iLbl = NULL; + bool isVisible = false; + int count = selectedPosInfoArr.Total(); + if (IsValidSize(count)) + { + // + // Loop Through Labels ... + for (int i = 0; i < count; i++) + { + // + iLbl = (CEdit *)selectedPosInfoArr.At(i); + isVisible = iLbl.IsVisible(); + if (isVisible) + { + iLbl.Hide(); + } + else + { + iLbl.Show(); + } + } + + // + // Update Button Text ... + isVisible = iLbl.IsVisible(); + string btnText = isVisible + ? "Hide Info" + : "Show Info"; + btnSelectedPosInfo.Text(btnText); + } + + // + ZeroMemory(iLbl); + } + + // + btnSelectedPosInfo.Pressed(false); + } + } + + // + // Check Positions Buttons ... + int posCount = posArray.Total(); + bool has = IsValidSize(posCount); + if (has) + { + // + for (int i = 0; i < posCount; i++) + { + // + CButton *iBtn = (CButton *)posArray.At(i); + + // + if (iBtn.Pressed()) + { + // + if (iBtn.IsEnabled()) + { + // + ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); + if (posID > 0 && selectedPositionID != posID) + { + selectedPositionID = posID; + UpdateGUIState(); + } + } + + // + iBtn.Pressed(false); + } + + // + ZeroMemory(iBtn); + } + } +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + delete mChartHelper; + ZeroMemory(mChartHelper); + + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + UpdatePositionButtons(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + UpdatePositionButtons(); +} + +/** + * 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 // +) +{ + // + UpdatePositionButtons(); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + // + // Update Position Buttons ... + UpdatePositionButtons(); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ +} + +// +// GUI Event Handlers and Helpers ... + +// +void HandleBuyTrade() +{ + HandleTrade(X_DIRECTION_BULLISH); +} + +// +void HandleSellTrade() +{ + HandleTrade(X_DIRECTION_BEARISH); +} + +// +void HandleTrade(ENUM_X_DIRECTION dir) +{ + // + if (!HasDirection(dir)) + { + return; + } + + // + string symbol = mChartHelper.Symbol(); + ENUM_TIMEFRAMES period = mChartHelper.Period(); + + // + bool isBullish = IsSpecifiedBullish(dir); + + // + double r2r = 1.5; + double volume = 0.01; + double riskInPoints = 100; + double point = GetPoints(symbol); + double entry = GetEntry(symbol, dir); + + // + double risk = riskInPoints * point; + double reward = risk * r2r; + + // + double sl = isBullish + ? entry - risk + : entry + risk; + double tp = isBullish + ? entry + reward + : entry - reward; + + // + string comment = ShortName + "_POS_" + ToXString(dir); + + // + if (isBullish) + { + // + eaTrader.Buy( + symbol, + period, + volume, + entry, + sl, + tp, + comment // + ); + } + else + { + // + eaTrader.Sell( + symbol, + period, + volume, + entry, + sl, + tp, + comment // + ); + } +} + +// +void HandleCloseTrade(ulong positionID) +{ + // + if (positionID == 0) + { + // + XPosition positions[]; + int count = eaTrader.GetPositions( + positions // + ); + bool has = IsValidSize(count); + if (has) + { + // + int closedCount = eaTrader.Close(positions); + has = IsValidSize(closedCount); + } + } + else + { + // + XPosition position; + bool has = eaTrader.GetPosition( + positionID, + position // + ); + if (has) + { + // + has = eaTrader.Close(positionID); + } + } +} + +// +ulong ExtractPositionIDFromButtonName(string name) +{ + // + ulong result = 0; + + // + string nameParts[]; + int namePartsCount = SplitContent(nameParts, name, "_"); + bool has = IsValidSize(namePartsCount); + if (has) + { + // + string lastPart = nameParts[namePartsCount - 1]; + StringReplace(lastPart, "_", ""); + result = (long)lastPart; + } + + // + ZeroMemory(nameParts); + + // + return result; +} + +// +void UpdatePositionButtons() +{ + // + // Retrieve Positions ... + XPosition positions[]; + int count = eaTrader.GetPositions( + positions // + ); + bool has = IsValidSize(count); + if (!has) + { + // + posArray.Clear(); + selectedPositionID = 0; + UpdateGUIState(); + return; + } + + // + posArray.Clear(); + + // + // Selected Position ID ... + bool isSelectdPositionIDExists = false; + if (has && selectedPositionID > 0) + { + // + for (int i = 0; i < count; i++) + { + // + if (!isSelectdPositionIDExists && + positions[i].ticket == selectedPositionID) + { + // + isSelectdPositionIDExists = true; + break; + } + } + } + if (!isSelectdPositionIDExists || + selectedPositionID == 0) + { + // + XPosition youngest; + int youngestIDX = GetXYoungest(youngest, positions); + bool hasYoungest = IsValidIndex(youngestIDX) && + youngest.IsValid(); + if (hasYoungest) + { + selectedPositionID = youngest.ticket; + } + + // + youngest.Clean(); + } + + // + int subWindow = 0; + ulong chartId = mChartHelper.ChartId(); + + // + int btnWidth = 25; + + // + int lastX = lblPositionIdSizeX + 5; + int lastSizeX = lastX + btnWidth; + + // + int lastY = lblPositionIdStartY; + int lastSizeY = lblPositionIdSizeY; + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPos = positions[i]; + + // + string posTypeStr = IsLong(iPos.type) + ? "LONG" + : "SHORT"; + + // + int iPosBtnX = lastX; + int iPosBtnSizeX = iPosBtnX + btnWidth; + string iPosBtnName = objSuffix + "_" + posTypeStr + "_POS_SELECT_BTN_" + ToXString(iPos.ticket); + + // + CButton *iPosBtn = new CButton(); + has = iPosBtn.Create( + chartId, + iPosBtnName, + subWindow, + iPosBtnX, + lastY, + iPosBtnSizeX, + lastSizeY // + ); + if (has) + { + // + // Apply Styles ... + string iPosBtnText = ToXString(iPos.ticket); + + // + iPosBtn.Text(iPosBtnText); + iPosBtn.Color(clrWhite); + + // + color iPosBtnBG = IsLong(iPos.type) + ? clrGreen + : clrDarkRed; + iPosBtn.ColorBackground(iPosBtnBG); + + // + lastX = iPosBtnSizeX + 5; + + // + if (selectedPositionID == iPos.ticket) + { + iPosBtn.Disable(); + } + + // + posArray.Add(iPosBtn); + } + + // + iPos.Clean(); + } + + // + ZeroMemory(positions); + UpdateGUIState(); +} + +// +void UpdateGUIState() +{ + // + // Update States Of Position Select Buttons ... + int count = posArray.Total(); + bool has = IsValidSize(count) && selectedPositionID > 0; + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + CButton *iBtn = (CButton *)posArray.At(i); + + // + ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); + + // + // Select Position ... + XPosition iPos; + bool hasPosition = eaTrader.GetPosition( + posID, + iPos // + ); + string iTooltip = + !hasPosition + ? "" + : IsLong(iPos.type) + ? "Long" + : "Short"; + + // + if (posID == selectedPositionID) + { + // + iBtn.Disable(); + iBtn.ColorBackground(clrDarkGray); + } + else + { + // + iBtn.Enable(); + + // + color iBtnBG = IsLong(iPos.type) + ? clrGreen + : clrDarkRed; + + // + iBtn.ColorBackground(iBtnBG); + } + + // + ZeroMemory(iBtn); + } + } + + // + // Update State of Close All ... + if (has && count > 1) + { + // + btnCloseAll.Enable(); + btnCloseAll.ColorBackground(clrDarkRed); + } + else + { + // + btnCloseAll.Disable(); + btnCloseAll.ColorBackground(clrDarkGray); + } + + // + // Update Selected Position Info Button State ... + if (has) + { + // + // Reading Global Chart Info ... + int subWindow = 0; + int chartWidth = mChartHelper.Width(); + ulong chartId = mChartHelper.ChartId(); + + // + // Read Selected Position ... + XPosition selectedPosition; + bool hasPosition = eaTrader.GetPosition( + selectedPositionID, + selectedPosition // + ); + + // + // Read All Positions ... + double profits = 0; + XPosition positions[]; + string positionsInfo = ""; + int positionsCount = eaTrader.GetPositions(positions); + has = IsValidSize(positionsCount); + if (has) + { + // + for (int i = 0; i < positionsCount; i++) + { + profits += positions[i].profit; + } + + // + if (positionsCount > 1) + { + positionsInfo = "Positions Count: " + ToXString(positionsCount) + ", Profits: " + ToXString(profits); + } + } + + // + if (hasPosition) + { + // + // Preparing Position Info ... + string posTicket = "Ticket: " + ToXString(selectedPosition.ticket); + string posType = "Type: " + ToXString(selectedPosition.type); + string posSymbolPeriod = + "Symbol: " + selectedPosition.symbol + ", " + + "Period: " + ToXString(selectedPosition.period); + string posProfit = "Profit: " + ToXString(selectedPosition.profit); + string posRiskToRewardRatio = "RiskToReward: " + ToXString(selectedPosition.GetRiskRewardRatio()); + string accountInfo = + "Balance: " + ToXString(eaTrader.mAccount.GetBalance()) + ", " + + "Equity: " + ToXString(eaTrader.mAccount.GetEquity()); + + // + string posInfos[]; + + // + // Ticket ... + Add( + posTicket, + posInfos // + ); + + // + // Type ... + Add( + posType, + posInfos // + ); + + // + // Symbol Period ... + Add( + posSymbolPeriod, + posInfos // + ); + + // + // Profit ... + Add( + posProfit, + posInfos // + ); + + // + // Risk to Reward Ratio ... + Add( + posRiskToRewardRatio, + posInfos // + ); + + // + // Add Positions Info if Exists ... + if (IsSpecifiedValid(positionsInfo)) + { + // + Add( + positionsInfo, + posInfos // + ); + + // + // Clear Info Array ... + selectedPosInfoArr.Clear(); + } + + // + // Adding Account Info ... + Add( + accountInfo, + posInfos // + ); + + // + // Create Button If Not Exists ... + if (btnSelectedPosInfo == NULL) + { + // + btnSelectedPosInfo = new CButton(); + + // + string name = objSuffix + "BTN_TOOGLE_SPOS_INFO"; + + // + int btnStartX = btnCloseStartX; + int btnSizeX = btnStartX + 200 + 5; + + // + int btnStartY = btnCloseSizeY + 5; + int btnSizeY = btnStartY + 50; + + // + bool isCreated = btnSelectedPosInfo.Create( + chartId, + name, + subWindow, + btnStartX, + btnStartY, + btnSizeX, + btnSizeY // + ); + if (!isCreated) + { + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + else + { + // + // Apply Styles ... + btnSelectedPosInfo.Color(clrYellow); + btnSelectedPosInfo.ColorBackground(clrDarkBlue); + } + } + + // + // Check Btn Exists ... + has = btnSelectedPosInfo != NULL; + if (has) + { + // + int posInfoCount = ArraySize(posInfos); + int lblInfoCount = selectedPosInfoArr.Total(); + has = IsValidSize(lblInfoCount) && lblInfoCount == posInfoCount; + + // + // Create info Labels ... + if (!has) + { + // + selectedPosInfoArr.Clear(); + has = IsValidSize(posInfoCount); + if (has) + { + // + // Creat Info Control ... + + // + string name = objSuffix + "LBL_SPOS_INFO"; + + // + int lblHeight = 25; + int lblWidth = 450; + + // + int startX = chartWidth - lblWidth - 5; + int sizeX = startX + lblWidth; + + // + int startY = 5; + int sizeY = startY + lblHeight; + + // + // Loop through Position Info's Array to Create Label Controls ... + for (int i = 0; i < posInfoCount; i++) + { + // + string iText = posInfos[i]; + string iTextMD5 = ToMD5(iText); + + // + string iName = name + "_" + iTextMD5; + + // + int iX1 = startX; + int iX2 = sizeX; + + // + int iY1 = startY; + int iY2 = startY + lblHeight; + + // + CEdit *iLbl = new CEdit(); + bool isCreated = iLbl.Create( + chartId, + iName, + subWindow, + iX1, + iY1, + iX2, + iY2 // + ); + if (isCreated) + { + // + iLbl.Text(iText); + iLbl.Color(clrYellow); + iLbl.ColorBorder(clrDarkSlateGray); + iLbl.ColorBackground(clrDarkSlateGray); + + // + selectedPosInfoArr.Add(iLbl); + + // + startY = iY2; + } + } + } + } + + // + // Update Info Labels ... + lblInfoCount = selectedPosInfoArr.Total(); + has = IsValidSize(lblInfoCount); + if (has) + { + // + CEdit *iLbl = NULL; + + // + // Loop Through Infos ... + for (int i = 0; i < lblInfoCount; i++) + { + // + iLbl = (CEdit *)selectedPosInfoArr.At(i); + + // + iLbl.Text(posInfos[i]); + } + + // + bool isVisible = iLbl.IsVisible(); + string btnText = isVisible + ? "Hide Info" + : "Show Info"; + btnSelectedPosInfo.Text(btnText); + + // + ZeroMemory(iLbl); + } + } + + // + ZeroMemory(posInfos); + } + + // + SpecifiedClean(positions); + } + else + { + // + // Toggle Selected Position Btn ... + if (btnSelectedPosInfo != NULL) + { + // + btnSelectedPosInfo.Destroy(); + + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + + // + // Selected Position Lbls ... + selectedPosInfoArr.Clear(); + } + + // + // Update State of BtnClose and BtnClose All ... + if (selectedPositionID == 0) + { + // + btnClose.Disable(); + btnClose.ColorBackground(clrDarkGray); + } + else + { + // + btnClose.Enable(); + btnClose.ColorBackground(clrDarkOrange); + } +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/BKP/tmp-trade_symbol.info.mq5 b/BKPS/14040626/Documents/BKP/tmp-trade_symbol.info.mq5 new file mode 100644 index 0000000..ebc5440 --- /dev/null +++ b/BKPS/14040626/Documents/BKP/tmp-trade_symbol.info.mq5 @@ -0,0 +1,977 @@ +` + // + // an Structure for Holds an Specified Symbols + // Positions Info ... + struct XTradeSymbolInfo +{ + // + // Properties ... + + // + string symbol; // Trading Symbol + + // + int longs; // All Long Trades + int shorts; // All Short Trades + + // + int trades; // All Trades + + // + int losses; // All Loosing Trades + int profits; // All Winning Trades + + // + datetime managedStart; // Managed Start Time + + // + int managedSLs; // Managed SL(s) + int managedTPs; // Managed TP(s) + int managedTrades; // Managed Trades + + // + double managedBalance; // Managed Start Balance + double managedProfits; // Managed Profit(s) + + // + // Constructor ... + XTradeSymbolInfo() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + + // + longs = 0; + shorts = 0; + + // + trades = 0; + + // + losses = 0; + profits = 0; + + // + managedStart = NULL; + + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + + // + managedBalance = 0; + managedProfits = 0; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol); + + // + return result; + } + + // + bool IsSameAs(XTradeSymbolInfo &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + // + string GetRestrictionDescription( + ENUM_XTRADE_RESTRICTION_PERIOD period // + ) + { + // + string result = NULL; + + // + if (!IsValid() || + !HasRestrictions(period)) + { + return result; + } + + // + result += + "-------------------" + "\n" + + "Restrictions: " + "\n" + + "-------------------" + "\n" + + "Symbol: " + ToXString(symbol) + "\n" + + "Period: " + ToXString(period) + "\n" + + "Start: " + ToFormatString(managedStart) + "\n" + + "Balance: " + ToXString(managedBalance) + "\n" + + "-------------------" + "\n" + + "Trades: " + ToXString(managedTrades) + "\n" + + "SL: " + ToXString(managedSLs) + "\n" + + "TP: " + ToXString(managedTPs) + "\n" + + "Profit: " + ToXString(managedProfits) + "\n" + + ""; + + // + return result; + } +}; + +// +void SetForceCloseTradesAt( + string _forceCloseAt // +) +{ + forceCloseAt = _forceCloseAt; +} + +// +void SetTradeSession( + string symbol, + string start, + string end, + string name = NULL // +) +{ + // + // Validate Args ... + bool has = IsValid(end) && + IsValid(start) && + IsValid(symbol); + if (!has) + { + return; + } + + // + // Create Session ... + + // + XTradeSession session; + + // + session.end = end; + session.name = name; + session.start = start; + + // + int sessionIDX = -1; + has = FindSymbolSession( + sessionIDX, + symbol // + ); + + // + if (!has) + { + // + // Add New Symbol Session ... + + // + XSymbolSessions iSymbolSession; + iSymbolSession.symbol = symbol; + + // + AddTradingSession( + session, + iSymbolSession // + ); + + // + AddRef( + iSymbolSession, + sessions // + ); + + // + iSymbolSession.Clean(); + } + else + { + // + // Update Trading Sessions of Exists Symbol Session ... + AddTradingSession( + session, + sessions[sessionIDX] // + ); + } + + // + // Cleanup Resources ... + session.Clean(); +} + +// +void SetTradeRestrictions( + ENUM_XTRADE_RESTRICTION_PERIOD _period, + int _maxAllowedTPs, + int _maxAllowedSLs, + int _maxAllowedTrades // +) +{ + // + // Normalizing Args ... + _maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0); + _maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0); + _maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0); + + // + restrictionsPeriod = _period; + maxAllowedTPs = _maxAllowedTPs; + maxAllowedSLs = _maxAllowedSLs; + maxAllowedTrades = _maxAllowedTrades; +} +// +// Symbol Info ... + +// +bool FindSymbolIndex( + int &index, + XTradeSymbolInfo &item // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = HasChild(symbols); + if (!result) + { + return result; + } + + // + index = FindIndex( + item, + symbols // + ); + + // + result = IsValidIndex(index); + + // + return result; +} + +// +bool FindSymbolIndex( + int &index, + string symbol // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(symbols); + if (!result) + { + return result; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + result = symbols[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +// +void AddOrUpdateSymbolInfo(XTradeSymbolInfo &item) +{ + // + bool has = item.IsValid(); + if (!has) + { + return; + } + + // + int index = -1; + bool isExists = FindSymbolIndex( + index, + item // + ); + if (!isExists) + { + // + AddRef( + item, + symbols // + ); + } + else + { + // + symbols[index].longs += item.longs; + symbols[index].shorts += item.shorts; + symbols[index].trades += item.trades; + symbols[index].losses += item.losses; + symbols[index].profits += item.profits; + symbols[index].managedSLs += item.managedSLs; + symbols[index].managedTPs += item.managedTPs; + symbols[index].managedTrades += item.managedTrades; + symbols[index].managedProfits += item.managedProfits; + + // + // Handle Remove on Managed SL based On Managed TP ... + if (item.managedTPs > 0) + { + // + symbols[index].managedSLs -= item.managedTPs; + if (symbols[index].managedSLs < 0) + { + symbols[index].managedSLs = 0; + } + } + + // + // Handle Remove on Managed TP based On Managed SL ... + if (item.managedSLs > 0) + { + // + symbols[index].managedTPs -= item.managedSLs; + if (symbols[index].managedTPs < 0) + { + symbols[index].managedTPs = 0; + } + } + } +} + +// +void ResetSymbolsRestrictions() +{ + // + bool has = HasChild(symbols); + if (has) + { + // + string prefix = "Protector: "; + + // + datetime start = TimeCurrent(); + double balance = trader.mAccount.GetBalance(); + bool hasRestrictions = HasRestrictions(restrictionsPeriod); + if (!hasRestrictions) + { + // + balance = 0; + start = NULL; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + XTradeSymbolInfo iInfo = symbols[i]; + if (reportRestrictions) + { + // + string message = iInfo.GetRestrictionDescription(restrictionsPeriod); + alert.SendAlert(message); + } + SaveRestrictions(iInfo); + + // + symbols[i].managedSLs = 0; + symbols[i].managedTPs = 0; + symbols[i].managedTrades = 0; + symbols[i].managedProfits = 0; + symbols[i].managedStart = start; + symbols[i].managedBalance = balance; + + // + iInfo.Clean(); + } + + // + string message = prefix + "Reset Symbols Restrictions"; + HandleReportProtector(message); + } +} + +// +void HandleRestrictions() +{ + // + bool isNewDay = timeTracker.IsNewDay(); + bool isNewHour = timeTracker.IsNewHour(); + bool isNewWeek = timeTracker.IsNewWeek(); + bool isNewMonth = timeTracker.IsNewMonth(); + + // + // Reset Force Closed Flag on new Day Starts ... + if (isNewDay) + { + isForceCloseAtTime = false; + } + + // + bool canResetRestrictions = + ( + // + // Hourly ... + (isNewHour && + restrictionsPeriod == XTRADE_RESTRICATION_HOURLY) + // + || + // + // Daily ... + (isNewDay && + restrictionsPeriod == XTRADE_RESTRICATION_DAILY) + // + || + // + // Weekly ... + (isNewWeek && + restrictionsPeriod == XTRADE_RESTRICATION_WEEKLY) + // + || + // + // Monthly ... + (isNewMonth && + restrictionsPeriod == XTRADE_RESTRICATION_MONTHLY) + // + ) + // + ; + if (canResetRestrictions) + { + ResetSymbolsRestrictions(); + } +} + +// +bool SaveRestrictions(XTradeSymbolInfo &info) +{ + // + bool result = false; + + // + if (!mSaveRestrictions) + { + return result; + } + + // + result = info.IsValid(); + if (!result) + { + return result; + } + + // + string filePath = GetRestrictionsFilePath(info.symbol); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = info.GetRestrictionDescription(restrictionsPeriod); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; +} + +// +// Symbol Session ... + +// +bool FindSymbolSession( + int &index, + string symbol // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(sessions); + if (!result) + { + return result; + } + + // + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +// +void AddTradingSession( + XTradeSession &session, + XSymbolSessions &symbolSession // +) +{ + // + bool has = session.IsValid() && + symbolSession.IsValid(); + if (!has) + { + return; + } + + // + // Check Session Exists in Symbol Session ... + bool isExists = false; + if (HasChild(symbolSession.sessions)) + { + // + int count = ArraySize(symbolSession.sessions); + for (int i = 0; i < count; i++) + { + // + isExists = symbolSession.sessions[i].end == session.end && + symbolSession.sessions[i].start == session.start; + if (isExists) + { + break; + } + } + } + + // + if (!isExists) + { + // + AddRef( + session, + symbolSession.sessions // + ); + } +} + +/** + * Check Signal Execution Conditions ... + * + * @param signal: XSignal instance reference ... + * @param executionResult: ENUM_X_SIGNAL_EXECUTION_RESULT member reference ... + * + * @return ( bool ) + */ +bool CheckSignal( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &executionResult // +) +{ + // + bool result = false; + + // + // Cleanup ... + executionResult = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Reporting Signal ... + if (reportSignals) + { + // + string message = signal.GetMessage("Provided"); + alert.SendAlert(message); + } + + // + SaveSignal(signal); + + // + // Check Trade Permission ... + if (!allowTrade) + { + // + result = false; + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + bool isLong = IsLong(signal.type); + bool isShort = IsShort(signal.type); + + // + bool isLongAndAllowed = + isLong && + allowLongs; + + // + bool isShortAndAllowed = + isShort && + allowShorts; + + // + result = isLongAndAllowed || + isShortAndAllowed; + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + // Check Symbol Info Exists or not ... + int symbolInfoIDX = -1; + bool isSymbolInfoExists = FindSymbolIndex( + symbolInfoIDX, + signal.symbol // + ); + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + signal.symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + // + result = sessions[symbolSessionIDX].CanTrade(); + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + + // + return result; + } + } + + // + // Check Trade Permissions Based on SL(s) Count ... + bool hasRestrictions = restrictionsPeriod != XTRADE_RESTRICATION_NONE; + if (hasRestrictions) + { + // + // Only Can Check Restrictions when + // Symbol Info Exists ... + if (isSymbolInfoExists) + { + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : symbols[symbolInfoIDX].managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : symbols[symbolInfoIDX].managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : symbols[symbolInfoIDX].managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + } + + // + // Report Error ... + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + + // + return result; + } + } + + // + return result; +} + +/** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCATBEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ +bool Execute(XSignal &signal) +{ + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = HasTrade( + idx, + signal // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT executionResult; + + // + // Checking Signal For Execution ... + result = CheckSignal( + signal, + executionResult // + ); + if (result) + { + // + result = trader.ExecuteSignal( + signal, + executionResult // + ); + } + + // + // Alert Signal Execution ... + if (reportTrades) + { + // + string executionMessage = ToString(executionResult); + + // + string message = NULL; + if (result) + { + message = signal.GetMessage("Executed"); + } + else + { + message = signal.GetMessage("Failed due (" + executionMessage + ")"); + } + + // + alert.SendAlert(message); + } + + // + if (result) + { + // + // Create Symbol Info Struct ... + XTradeSymbolInfo iSymbolInfo; + + // + iSymbolInfo.trades = 1; + iSymbolInfo.managedTrades = 1; + iSymbolInfo.symbol = signal.symbol; + + // + bool isLong = IsLong(signal.type); + if (isLong) + { + iSymbolInfo.longs = 1; + } + else + { + iSymbolInfo.shorts = 1; + } + + // + // Fill Balance for Restrications ... + bool hasRestrictions = HasRestrictions(restrictionsPeriod); + if (hasRestrictions) + { + // + // Read Balance ... + double balance = trader.mAccount.GetBalance(); + iSymbolInfo.managedBalance = balance; + iSymbolInfo.managedStart = TimeCurrent(); + } + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + // Create Trade Struct ... + XTradeInfo iTrade; + + // + ulong positionID = trader.GetLastOpenPositionTicket(); + double commission = trader.GetPositionCommission(positionID); + + // + iTrade.signal = signal; + iTrade.positionID = positionID; + iTrade.commission = commission; + iTrade.signaledAt = signal.time; + iTrade.executedAt = TimeCurrent(); + iTrade.conditions = signal.conditions; + + // + AddRef( + iTrade, + trades // + ); + } + + // + return result; +} + + /** + * Check Specified Symbol is Active for + * Analysing or Open Trades ... + */ + bool IsActiveSession(string symbol) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + // TODO: Complete this ... + + // // + // // Check Symbol Session Exists or not ... + // int symbolSessionIDX = -1; + // bool isSymbolSessionExists = FindSymbolSession( + // symbolSessionIDX, + // symbol // + // ); + + // // + // // Chack Trade Session Validating ... + // if (isSymbolSessionExists) + // { + // result = sessions[symbolSessionIDX].CanTrade(); + // } + + // + return result; + } + +// +string forceCloseAt; +bool isForceCloseAtTime; + +// +int maxAllowedTPs; +int maxAllowedSLs; +int maxAllowedTrades; +ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; + +XTradeSymbolInfo symbols[]; +XSymbolSessions sessions[]; + +// +forceCloseAt = NULL; +isForceCloseAtTime = false; + +// +maxAllowedTPs = 0; +maxAllowedSLs = 0; +maxAllowedTrades = 0; +restrictionsPeriod = XTRADE_RESTRICATION_NONE; diff --git a/BKPS/14040626/Documents/BKP/tmp.backtester.codes.mq5 b/BKPS/14040626/Documents/BKP/tmp.backtester.codes.mq5 new file mode 100644 index 0000000..47bd1e6 --- /dev/null +++ b/BKPS/14040626/Documents/BKP/tmp.backtester.codes.mq5 @@ -0,0 +1,747 @@ + +void UpdateMainPanel() +{ + // + // Validate ... + if (mChartHelper == NULL || + mainPanel == NULL) + { + return; + } + + // + bool has = false; + + // + // Update Main Panel Position ... + XObjPosition mainPanelPosition; + CalculateMainPanelPosition(mainPanelPosition); + if (mainPanelPosition.IsValidForRectangle()) + { + // + has = mainPanel.ShiftPoint(1, mainPanelPosition.fromTime, mainPanelPosition.fromPrice); + if (has) + { + has = mainPanel.ShiftPoint(2, mainPanelPosition.toTime, mainPanelPosition.toPrice); + } + } +} + +/** + * Calculate Main Window Position ... + * + * @param position: XObjPosition + */ +void CalculateMainPanelPosition(XObjPosition &position) +{ + // + position.Clean(); + + // + // Reading Chart Helper Requirements ... + + // + string mChartSymbol = mChartHelper.Symbol(); + double mPoint = GetPoints(mChartSymbol); + + // + ENUM_TIMEFRAMES mChartPeriod = mChartHelper.Period(); + int mChartPeriodSeconds = PeriodSeconds(mChartPeriod); + + // + double mChartMinPrice = mChartHelper.PriceMin(); + double mChartMaxPrice = mChartHelper.PriceMax(); + int mChartVisibleBarsCount = mChartHelper.VisibleBars(); + int mChartFirstBarIndex = mChartHelper.FirstVisibleBar(); + + // + datetime mChartFirstBarTime = GetBarTime( + mChartSymbol, + mChartPeriod, + mChartFirstBarIndex // + ); + + // + position.fromTime = mChartFirstBarTime + (mChartPeriodSeconds); + position.fromPrice = mChartMaxPrice - (10 * mPoint); + + // + position.toTime = position.fromTime + (40 * mChartPeriodSeconds); + position.toPrice = position.fromPrice - (20 * mPoint); + + // + Print(" "); + + // + Print("From Time: ", position.fromTime); + Print("To Time: ", position.toTime); + + // + Print(" "); + + // + Print("From Price: ", position.fromPrice); + Print("To Price: ", position.toPrice); +} + +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XBackTester +// Description: a Backtest Tools Strategy Tester +// +// 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 XBackTester" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-chart.helper.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Import Chart Objects ... +#include +#include +#include +#include +#include +#include +#include + +// +// Definitions ... +struct XObjPosition +{ + // + // Props ... + datetime fromTime; + double fromPrice; + datetime toTime; + double toPrice; + + // + // Constructor ... + XObjPosition() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + toPrice = 0; + fromPrice = 0; + + // + toTime = NULL; + fromTime = NULL; + } + + // + // Validate XWindowPosition for Rectangle ... + bool IsValidForRectangle() + { + // + bool result = + // + toPrice > 0 && + fromPrice > 0 && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime) && + fromTime < toTime + // + ; + + // + return result; + } +}; + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XCTrade *eaTrader; // Trader of Expert Adviser ... + +// +// Chart Objects and Properties ... +XCChartHelper *mChartHelper; + +// +// Chart Object Class ... + +// +string objSuffix; + +// +// Main Panel ... +string mainPanelName; +CChartObjectRectLabel *mainPanel; // Main Panel ... +string buyButtonName; +CChartObjectButton *buyButton; // Buy Button ... +string sellButtonName; +CChartObjectButton *sellButton; // Sell Button ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); +} + +// +// 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 ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + // + if (mainPanel != NULL && sparam == mainPanelName) + { + // + Print("Main Panel Clicked ..."); + } + } +} + +// +// 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; + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XCTrade( + eaSlippage, + eaMagicNumber // + ); + + // + // TODO: Fix This ... + result = true; + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaAlert; +} + +// +// GUI Events ... + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + int subWindow = 0; + ulong chartId = ChartID(); + objSuffix = ShortName + "_"; + + // + // Initial Chart Class Instance ... + mChartHelper = new XCChartHelper(chartId); + + // + // Create Main Panel ... + result = CreateMainPanel(); + + // + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // UpdateMainPanel(); +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + delete mChartHelper; + ZeroMemory(mChartHelper); + + // + delete mainPanel; + ZeroMemory(mainPanel); +} + +// +// Custom Helper Functions ... + +bool CreateMainPanel() +{ + // + bool result = false; + + // + if (mChartHelper == NULL) + { + return result; + } + + // + int subWindow = 0; + + // + mainPanelName = objSuffix + "Main_Panel"; + mainPanel = new CChartObjectRectLabel(); + result = mainPanel.Create( + mChartHelper.ChartId(), + mainPanelName, + subWindow, + 10, + 25, + 400, + 200 // + ); + if (!result) + { + return result; + } + + // + // Styling Main Panel ... + mainPanel.BackColor(clrDarkGray); + mainPanel.Tooltip(mainPanelName); + + // + // Create Buttons ... + buyButtonName = objSuffix + "BTN_BUY"; + buyButton = new CChartObjectButton(); + result = buyButton.Create( + mChartHelper.ChartId(), + buyButtonName, + subWindow, + 10, + 25, + 200, + 100 // + ); + if (!result) + { + return result; + } + + // + // Apply Style of Buy Button ... + + if (result) + { + } + + // + return result; +} + +////////////////////////////////////////////////// + +// +// class XCEdit : public CEdit { +// // +// public: +// // +// string mValue; + +// // +// bool OnSetText() { +// // +// Print("Object Edit End ..."); +// return true; +// } +// }; + +// CEdit edtPositionId; + +// // +// // EDIT Position ID ... +// int edtPositionIdStartX = btnSellStartX; +// int edtPositionIdSizeX = edtPositionIdStartX + 100; +// int edtPositionIdStartY = btnSellSizeY + 5; +// int edtPositionIdSizeY = edtPositionIdStartY + 50; +// string edtPositionIdName = objSuffix + "EDT_POS_ID"; +// result = edtPositionId.Create( +// chartId, +// edtPositionIdName, +// subWindow, +// edtPositionIdStartX, +// edtPositionIdStartY, +// edtPositionIdSizeX, +// edtPositionIdSizeY // +// ); +// if (result) +// { +// // +// // Apply Edit Position ID Style ... +// edtPositionId.Text(ToXString(selectedPositionID)); +// edtPositionId.TextAlign(ALIGN_LEFT); +// } + + +////////////////////////////////////////////////////////////////// + + +// +CButton btnPauseReplay; +bool isVisualTesterPaused = false; + + // + // Initial Btn Pause Play ... + int subWindow = 0; + int defaultGap = 5; + int defaultWidth = 100; + int defaultHeight = 30; + ulong chartId = eaExpert.eaChartHelper.ChartId(); + + // + int btnPauseReplayX1 = defaultGap; + int btnPauseReplayX2 = btnPauseReplayX1 + defaultWidth; + int btnPauseReplayY1 = eaExpert.eaChartHelper.Height() - defaultHeight - defaultGap; + int btnPauseReplayY2 = btnPauseReplayY1 + defaultHeight; + + // + string btnPauseReplayName = ShortName + "BTN_PAUSE_REPLAY"; + + // + isInited = btnPauseReplay.Create( + chartId, + btnPauseReplayName, + subWindow, + btnPauseReplayX1, + btnPauseReplayY1, + btnPauseReplayX2, + btnPauseReplayY2 // + ); + if (isInited) + { + // + // Apply Style ... + string btnPauseReplayText = + isVisualTesterPaused + ? "Play" + : "Pause"; + btnPauseReplay.Text(btnPauseReplayText); + btnPauseReplay.Color(clrAzure); + btnPauseReplay.ColorBackground(clrBlack); + } + +// + // + // Update btn Pause Replay ... + string btnPauseReplayText = + isVisualTesterPaused + ? "Play" + : "Pause"; + btnPauseReplay.Text(btnPauseReplayText); + if (IsRunningeOnTestVisualMode()) + { + // + btnPauseReplay.Show(); + btnPauseReplay.Enable(); + } + else + { + // + btnPauseReplay.Hide(); + btnPauseReplay.Enable(); + } + if (btnPauseReplay.Pressed()) + { + // + if (btnPauseReplay.IsEnabled()) + { + // + HandlePauseStrategyTester(); + + // + btnPauseReplayText = + isVisualTesterPaused + ? "Play" + : "Pause"; + btnPauseReplay.Text(btnPauseReplayText); + } + + // + btnPauseReplay.Pressed(false); + } + + +void HandlePauseStrategyTester() +{ + // + isVisualTesterPaused = !isVisualTesterPaused; + + // + // DebugBreak(); + + keybd_event(VK_SPACE, 0, 0, 0); + keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0); +} diff --git a/BKPS/14040626/Documents/BKP/tmp.codes.mq5 b/BKPS/14040626/Documents/BKP/tmp.codes.mq5 new file mode 100644 index 0000000..003f38b --- /dev/null +++ b/BKPS/14040626/Documents/BKP/tmp.codes.mq5 @@ -0,0 +1,2048 @@ + // + int minRequiredRange = 20; + if (barIndex > maxBarIndex - minRequiredRange - 4) + { + return; + } + + // + double iP2SCLL = sLLBuffer[barIndex + 2]; + double iP2SCHH = sHHBuffer[barIndex + 2]; + + // + double iP3SCLL = sLLBuffer[barIndex + 3]; + double iP3SCHH = sHHBuffer[barIndex + 3]; + + // + double iP4SCLL = sLLBuffer[barIndex + 4]; + double iP4SCHH = sHHBuffer[barIndex + 4]; + + // + double iP2MCLL = mLLBuffer[barIndex + 2]; + double iP2MCHH = mHHBuffer[barIndex + 2]; + + // + double iP3MCLL = mLLBuffer[barIndex + 3]; + double iP3MCHH = mHHBuffer[barIndex + 3]; + + // + double iP4MCLL = mLLBuffer[barIndex + 4]; + double iP4MCHH = mHHBuffer[barIndex + 4]; + + // + double iP2LCLL = lLLBuffer[barIndex + 2]; + double iP2LCHH = lHHBuffer[barIndex + 2]; + + // + double iP3LCLL = lLLBuffer[barIndex + 3]; + double iP3LCHH = lHHBuffer[barIndex + 3]; + + // + double iP4LCLL = lLLBuffer[barIndex + 4]; + double iP4LCHH = lHHBuffer[barIndex + 4]; + + // + double iP2HCLL = hLLBuffer[barIndex + 2]; + double iP2HCHH = hHHBuffer[barIndex + 2]; + + // + double iP3HCLL = hLLBuffer[barIndex + 3]; + double iP3HCHH = hHHBuffer[barIndex + 3]; + + // + double iP4HCLL = hLLBuffer[barIndex + 4]; + double iP4HCHH = hHHBuffer[barIndex + 4]; + + // + // Cycle States ... + + // + // Create Conditions ... + + // + bool isSCMaOverMCMa = iSCMa > iMCMa; + bool isPSCMaOverMCMa = iPSCMa > iPMCMa; + + // + bool isSCMaUnderMCMa = iSCMa < iMCMa; + bool isPSCMaUnderMCMa = iPSCMa < iPMCMa; + + // + bool isSCMaCrossedOverMCMa = + isSCMaOverMCMa && + !isPSCMaOverMCMa; + + // + bool isSCMaCrossedUnderMCMa = + isSCMaUnderMCMa && + !isPSCMaUnderMCMa; + + // + bool isLCMaOverHCMa = iLCMa > iHCMa; + bool isPLCMaOverHCMa = iPLCMa > iPHCMa; + + // + bool isLCMaUnderHCMa = iLCMa < iHCMa; + bool isPLCMaUnderHCMa = iPLCMa < iPHCMa; + + // + bool isLCMaCrossedOverHCMa = + isLCMaOverHCMa && + !isPLCMaOverHCMa; + + // + bool isLCMaCrossedUnderHCMa = + isLCMaUnderHCMa && + !isPLCMaUnderHCMa; + + // + // SC State ... + + // + bool isSCMaBullish = + iSCMaState == bullishState; + bool isPSCMaBullish = + iPSCMaState == bullishState; + + // + bool isSCMaBearish = + iSCMaState == bearishState; + bool isPSCMaBearish = + iPSCMaState == bearishState; + + // + bool isSCMaSwitchedToBullish = + isSCMaBullish && + !isPSCMaBullish; + + // + bool isSCMaSwitchedToBearish = + isSCMaBearish && + !isPSCMaBearish; + + // + bool isSCLLOverMCLL = + iSCLL > iMCLL; + bool isPSCLLOverMCLL = + iPSCLL > iPMCLL; + bool isP2SCLLOverMCLL = + iP2SCLL > iP2MCLL; + bool isP3SCLLOverMCLL = + iP3SCLL > iP3MCLL; + bool isP4SCLLOverMCLL = + iP4SCLL > iP4MCLL; + + // + bool isSCHHUnderMCHH = + iSCHH < iMCHH; + bool isPSCHHUnderMCHH = + iPSCHH < iPMCHH; + bool isP2SCHHUnderMCHH = + iP2SCHH < iP2MCHH; + bool isP3SCHHUnderMCHH = + iP3SCHH < iP3MCHH; + bool isP4SCHHUnderMCHH = + iP4SCHH < iP4MCHH; + + // + bool isSCLLCrossedOverMCLL = + isSCLLOverMCLL && + !isPSCLLOverMCLL; + bool isPSCLLCrossedOverMCLL = + isPSCLLOverMCLL && + !isP2SCLLOverMCLL; + bool isP2SCLLCrossedOverMCLL = + isP2SCLLOverMCLL && + !isP3SCLLOverMCLL; + bool isP3SCLLCrossedOverMCLL = + isP3SCLLOverMCLL && + !isP4SCLLOverMCLL; + + // + bool isSCHHCrossedUnderMCHH = + isSCHHUnderMCHH && + !isPSCHHUnderMCHH; + bool isPSCHHCrossedUnderMCHH = + isPSCHHUnderMCHH && + !isP2SCHHUnderMCHH; + bool isP2SCHHCrossedUnderMCHH = + isP2SCHHUnderMCHH && + !isP3SCHHUnderMCHH; + bool isP3SCHHCrossedUnderMCHH = + isP3SCHHUnderMCHH && + !isP4SCHHUnderMCHH; + + // + // MC State ... + + // + bool isMCMaBullish = + iMCMaState == bullishState; + bool isPMCMaBullish = + iPMCMaState == bullishState; + + // + bool isMCMaBearish = + iMCMaState == bearishState; + bool isPMCMaBearish = + iPMCMaState == bearishState; + + // + bool isMCMaSwitchedToBullish = + isMCMaBullish && + !isPMCMaBullish; + + // + bool isMCMaSwitchedToBearish = + isMCMaBearish && + !isPMCMaBearish; + + // + bool isMCLLOverLCLL = + iMCLL > iLCLL; + bool isPMCLLOverLCLL = + iPMCLL > iPLCLL; + bool isP2MCLLOverLCLL = + iP2MCLL > iP2LCLL; + bool isP3MCLLOverLCLL = + iP3MCLL > iP3LCLL; + bool isP4MCLLOverLCLL = + iP4MCLL > iP4LCLL; + + // + bool isMCHHUnderLCHH = + iMCHH < iLCHH; + bool isPMCHHUnderLCHH = + iPMCHH < iPLCHH; + bool isP2MCHHUnderLCHH = + iP2MCHH < iP2LCHH; + bool isP3MCHHUnderLCHH = + iP3MCHH < iP3LCHH; + bool isP4MCHHUnderLCHH = + iP4MCHH < iP4LCHH; + + // + bool isMCLLCrossedOverLCLL = + isMCLLOverLCLL && + !isPMCLLOverLCLL; + bool isPMCLLCrossedOverLCLL = + isPMCLLOverLCLL && + !isP2MCLLOverLCLL; + bool isP2MCLLCrossedOverLCLL = + isP2MCLLOverLCLL && + !isP3MCLLOverLCLL; + bool isP3MCLLCrossedOverLCLL = + isP3MCLLOverLCLL && + !isP4MCLLOverLCLL; + + // + bool isMCHHCrossedUnderLCHH = + isMCHHUnderLCHH && + !isPMCHHUnderLCHH; + bool isPMCHHCrossedUnderLCHH = + isPMCHHUnderLCHH && + !isP2MCHHUnderLCHH; + bool isP2MCHHCrossedUnderLCHH = + isP2MCHHUnderLCHH && + !isP3MCHHUnderLCHH; + bool isP3MCHHCrossedUnderLCHH = + isP3MCHHUnderLCHH && + !isP4MCHHUnderLCHH; + + // + // LC State ... + + // + bool isLCMaBullish = + iLCMaState == bullishState; + bool isPLCMaBullish = + iPLCMaState == bullishState; + + // + bool isLCMaBearish = + iLCMaState == bearishState; + bool isPLCMaBearish = + iPLCMaState == bearishState; + + // + bool isLCMaSwitchedToBullish = + isLCMaBullish && + !isPLCMaBullish; + + // + bool isLCMaSwitchedToBearish = + isLCMaBearish && + !isPLCMaBearish; + + // + bool isLCLLOverHCLL = + iLCLL > iHCLL; + bool isPLCLLOverHCLL = + iPLCLL > iPHCLL; + bool isP2LCLLOverHCLL = + iP2LCLL > iP2HCLL; + bool isP3LCLLOverHCLL = + iP3LCLL > iP3HCLL; + bool isP4LCLLOverHCLL = + iP4LCLL > iP4HCLL; + + // + bool isLCHHUnderHCHH = + iLCHH < iHCHH; + bool isPLCHHUnderHCHH = + iPLCHH < iPHCHH; + bool isP2LCHHUnderHCHH = + iP2LCHH < iP2HCHH; + bool isP3LCHHUnderHCHH = + iP3LCHH < iP3HCHH; + bool isP4LCHHUnderHCHH = + iP4LCHH < iP4HCHH; + + // + bool isLCLLCrossedOverHCLL = + isLCLLOverHCLL && + !isPLCLLOverHCLL; + bool isPLCLLCrossedOverHCLL = + isPLCLLOverHCLL && + !isP2LCLLOverHCLL; + bool isP2LCLLCrossedOverHCLL = + isP2LCLLOverHCLL && + !isP3LCLLOverHCLL; + bool isP3LCLLCrossedOverHCLL = + isP3LCLLOverHCLL && + !isP4LCLLOverHCLL; + + // + bool isLCHHCrossedUnderHCHH = + isLCHHUnderHCHH && + !isPLCHHUnderHCHH; + bool isPLCHHCrossedUnderHCHH = + isPLCHHUnderHCHH && + !isP2LCHHUnderHCHH; + bool isP2LCHHCrossedUnderHCHH = + isP2LCHHUnderHCHH && + !isP3LCHHUnderHCHH; + bool isP3LCHHCrossedUnderHCHH = + isP3LCHHUnderHCHH && + !isP4LCHHUnderHCHH; + + // + // HC State ... + + // + bool isHCMaBullish = + iHCMaState == bullishState; + bool isPHCMaBullish = + iPHCMaState == bullishState; + + // + bool isHCMaBearish = + iHCMaState == bearishState; + bool isPHCMaBearish = + iPHCMaState == bearishState; + + // + bool isHCMaSwitchedToBullish = + isHCMaBullish && + !isPHCMaBullish; + + // + bool isHCMaSwitchedToBearish = + isHCMaBearish && + !isPHCMaBearish; + +/////////////////////////////////////////////////////////////////////////////// + + // + // HK Signal Bar ... + + // + double iHKSOpen = hkSBarOpenBuffer[barIndex]; + double iHKSClose = hkSBarCloseBuffer[barIndex]; + + // + double iHKSMax = MathMax(iHKSOpen, iHKSClose); + double iHKSMin = MathMin(iHKSOpen, iHKSClose); + + // + bool isHKSBullish = hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex]; + bool isPHKSBullish = hkSBarOpenBuffer[barIndex + 1] < hkSBarCloseBuffer[barIndex + 1]; + + // + bool isHKSBearish = hkSBarOpenBuffer[barIndex] > hkSBarCloseBuffer[barIndex]; + bool isPHKSBearish = hkSBarOpenBuffer[barIndex + 1] > hkSBarCloseBuffer[barIndex + 1]; + + // + bool isHKSSwitchedToBullish = + isHKSBullish && + !isPHKSBullish; + + // + bool isHKSSwitchedToBearish = + isHKSBearish && + !isPHKSBearish; + + // + // TREND ... + + // + double iTrend = trendBuffer[barIndex]; + bool isTrendBullish = trendStateBuffer[barIndex] > 0; + bool isTrendBearish = trendStateBuffer[barIndex] < 0; + bool isTrendSwitchedToBullish = + trendStateBuffer[barIndex] > 0 && + trendStateBuffer[barIndex + 1] <= 0; + bool isTrendSwitchedToBearish = + trendStateBuffer[barIndex] < 0 && + trendStateBuffer[barIndex + 1] >= 0; + + // + // RSI ... + + // + bool isRSIOverOB = rsiBuffer[barIndex] > rsiOBLevel; + bool isPRSIOverOB = rsiBuffer[barIndex + 1] > rsiOBLevel; + + // + bool isRSIUnderOB = rsiBuffer[barIndex] < rsiOBLevel; + bool isPRSIUnderOB = rsiBuffer[barIndex + 1] < rsiOBLevel; + + // + bool isRSICrossedOverOB = + isRSIOverOB && + !isPRSIOverOB; + + // + bool isRSICrossedUnderOB = + isRSIUnderOB && + !isPRSIUnderOB; + + // + bool isRSIOverOS = rsiBuffer[barIndex] > rsiOSLevel; + bool isPRSIOverOS = rsiBuffer[barIndex + 1] > rsiOSLevel; + + // + bool isRSIUnderOS = rsiBuffer[barIndex] < rsiOSLevel; + bool isPRSIUnderOS = rsiBuffer[barIndex + 1] < rsiOSLevel; + + // + bool isRSICrossedOverOS = + isRSIOverOS && + !isPRSIOverOS; + + // + bool isRSICrossedUnderOS = + isRSIUnderOS && + !isPRSIUnderOS; + + // + // ADX ... + + // + bool isADXOverThreshold = adxBuffer[barIndex] > adxThreshold; + bool isPADXOverThreshold = adxBuffer[barIndex + 1] > adxThreshold; + + // + bool isADXUnderThreshold = adxBuffer[barIndex] < adxThreshold; + bool isPADXUnderThreshold = adxBuffer[barIndex + 1] < adxThreshold; + + // + bool isADXCrossedOverThreshold = + isADXOverThreshold && + !isPADXOverThreshold; + + // + bool isADXCrossedUnderThreshold = + isADXUnderThreshold && + !isPADXUnderThreshold; + + // + bool isADXBullish = adxpBuffer[barIndex] > adxnBuffer[barIndex]; + bool isPADXBullish = adxpBuffer[barIndex + 1] > adxnBuffer[barIndex + 1]; + + // + bool isADXBearish = adxpBuffer[barIndex] < adxnBuffer[barIndex]; + bool isPADXBearish = adxpBuffer[barIndex + 1] < adxnBuffer[barIndex + 1]; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + + // + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + bool isADXFullySwitchedToBullish = + isADXSwitchedToBullish && + isADXCrossedOverThreshold; + + // + bool isADXFullySwitchedToBearish = + isADXSwitchedToBearish && + isADXCrossedUnderThreshold; + + // + bool isTriggerBarOverHKS = + iBar.low > iHKSMax; + bool isTriggerBarUnderHKS = + iBar.high < iHKSMin; + + // + // KI ... + + // + bool isKIBullish = kiStateBuffer[barIndex] > 0; + bool isPKIBullish = kiStateBuffer[barIndex + 1] > 0; + + // + bool isKIBearish = kiStateBuffer[barIndex] < 0; + bool isPKIBearish = kiStateBuffer[barIndex = 1] < 0; + + // // + // bool isKIOverHKS = + // kiBuffer[barIndex] > iHKSMax; + + // // + // bool isKIUnderHKS = + // kiBuffer[barIndex] < iHKSMin; + + // + bool isKISwitchedToBullish = + isKIBullish && + !isPKIBullish; + + // + bool isKISwitchedToBearish = + isKIBearish && + !isPKIBearish; + + // + // Detecting Signal ... + + // + // Bullish ... + isBullish = + // + false + // Conditions Validation ... + // isKIOverHKS && + // isHKSBullish && + // isKISwitchedToBullish + // && + // + // Bar Validation ... + // iBar.IsBullish() && + // iBar.close > kiBuffer[barIndex] + // + ; + + // + // Bearish ... + isBearish = + // + false + // Conditions Validation ... + // isKIUnderHKS && + // isHKSBearish && + // isKISwitchedToBearish + // && + // + // Bar Validation ... + // iBar.IsBearish() && + // iBar.close < kiBuffer[barIndex] + // + ; + +//////////////////////////////////////////////////////////////////// + + +// +int mSameKICount = 0; +int mSameKIBullishCount = 0; +int mSameKIBearishCount = 0; + +// +int mSamePeakCount = 0; +int mSameValeCount = 0; + +// +double mSamePeaksGoldenMin = 0; +double mSamePeaksGoldenMax = 0; + +// +double mSameValesGoldenMin = 0; +double mSameValesGoldenMax = 0; + +// +int mSamePeakGoldenCount = 0; +int mSameValeGoldenCount = 0; + +// +bool mDrawLiquidities = false; +bool mDrawRangeBreakes = false; + +// +bool mDetectLiquidities = true; +bool mDetectRangeBreakes = true; + +// +XBoxZone mBullishLiquidities[]; +XBoxZone mBearishLiquidities[]; +XBoxZone mBullishRangeBreakes[]; +XBoxZone mBearishRangeBreakes[]; + +// +// POI(s) Handlers ... +// + +/** + * Detect POI(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DetectPOIs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Some Requirements ... + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Handle Minimum Required Bars ... + bool isPassedRequiredBars = barIndex < maxBarIndex - 3; + if (!isPassedRequiredBars) + { + return; + } + + // + // Recieve Bar ... + XOHCL iBar; + XOHCL iPBar; + bool has = iBar.Init( + _Symbol, + _Period, + barIndex + // + ); + has = + has && + iBar.GetPreviousBar(iPBar); + if (!has) + { + return; + } + + // + bool isBullish = false; + bool isBearish = false; + int maxAllowedPOIs = 50; + + // + ENUM_X_DIRECTION iDir; + + // + // Detecting Liquidity ... + if (mDetectLiquidities) + { + // + bool isLiquidity = + mBarAnalyser + .IsRejected( + iBar, + iDir, + true, + true // + ); + bool isBullishLiquiditySweeped = + isLiquidity && + IsBullish(iDir); + bool isBearishLiquiditySweeped = + isLiquidity && + IsBearish(iDir); + if (isLiquidity) + { + // + XBoxZone iLiq; + + // + iLiq.dir = iDir; + iLiq.type = "XLIQ"; + iLiq.upper = + isBullishLiquiditySweeped + ? iBar.GetDown() + : iBar.high; + iLiq.lower = + isBullishLiquiditySweeped + ? iBar.low + : iBar.GetUp(); + iLiq.at = iBar.time; + iLiq.from = iBar.time; + iLiq.symbol = _Symbol; + iLiq.period = _Period; + iLiq.to = ((datetime)((int)iBar.time + (PeriodSeconds(_Period)))); + + // + if (iLiq.IsValid()) + { + // + if (isBullishLiquiditySweeped) + { + // + has = AddBoxIfNotExists( + iLiq, + mBullishLiquidities // + ); + if (has) + { + // + SortBoxes( + mBullishLiquidities, + maxAllowedPOIs // + ); + } + } + else + { + // + has = AddBoxIfNotExists( + iLiq, + mBearishLiquidities // + ); + if (has) + { + // + SortBoxes( + mBearishLiquidities, + maxAllowedPOIs // + ); + } + } + } + + // + iLiq.Clean(); + } + } + + // + // Detecting Bullish and Bearish Breakes ... + + // + bool isPeakSame = peakBuffer[barIndex] == peakBuffer[barIndex + 1]; + bool isPPeakSame = peakBuffer[barIndex + 1] == peakBuffer[barIndex + 2]; + + // + bool isPeakOverLast = peakBuffer[barIndex] > peakBuffer[barIndex + 1]; + bool isPPeakOverLast = peakBuffer[barIndex + 1] > peakBuffer[barIndex + 2]; + + // + bool isPeakUnderLast = peakBuffer[barIndex] < peakBuffer[barIndex + 1]; + bool isPPeakUnderLast = peakBuffer[barIndex + 1] < peakBuffer[barIndex + 2]; + + // + bool isSamePeakOverLast = + isPPeakSame && + isPeakOverLast; + bool isSamePeakUnderLast = + isPPeakSame && + isPeakUnderLast; + + // + bool isValeSame = valeBuffer[barIndex] == valeBuffer[barIndex + 1]; + bool isPValeSame = valeBuffer[barIndex + 1] == valeBuffer[barIndex + 2]; + + // + bool isValeOverLast = valeBuffer[barIndex] > valeBuffer[barIndex + 1]; + bool isPValeOverLast = valeBuffer[barIndex + 1] > valeBuffer[barIndex + 2]; + + // + bool isValeUnderLast = valeBuffer[barIndex] < valeBuffer[barIndex + 1]; + bool isPValeUnderLast = valeBuffer[barIndex + 1] < valeBuffer[barIndex + 2]; + + // + bool isSameValeOverLast = + isPValeSame && + isValeOverLast; + bool isSameValeUnderLast = + isPValeSame && + isValeUnderLast; + + // + // Detecting Range Breakes ... + if (mDetectRangeBreakes) + { + // + isBullish = isSamePeakOverLast + // || isSameValeOverLast + ; + isBearish = + isSameValeUnderLast + // || isSamePeakUnderLast + ; + + // + bool basedOnPeak = + isSamePeakOverLast + // || isSamePeakUnderLast + ; + + // + bool basedOnVale = + isSameValeUnderLast + // isSameValeOverLast || + ; + + // + has = isBullish || + isBearish; + + // + if (has) + { + // + XBoxZone iRNGBreak; + + // + iDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + iRNGBreak.dir = iDir; + iRNGBreak.at = iBar.time; + iRNGBreak.type = "XRNGB"; + iRNGBreak.to = iBar.time; + iRNGBreak.symbol = _Symbol; + iRNGBreak.period = _Period; + + // + int fromIDX = + iBar.Index() + + (basedOnPeak + ? mSamePeakCount + : basedOnVale + ? mSameValeCount + : 0); + datetime from = GetBarTime( + _Symbol, + _Period, + fromIDX // + ); + iRNGBreak.from = from; + + // + double upper = + isBullish + ? basedOnPeak + ? peakBuffer[barIndex] + : basedOnVale + ? mSameValeGoldenCount + : 0 + : isBearish + ? basedOnPeak + ? peakBuffer[barIndex] + : basedOnVale + ? mSameValeGoldenCount + : 0 + : 0; + + // + double lower = + isBullish + ? basedOnPeak + ? mSamePeakGoldenCount + : basedOnVale + ? valeBuffer[barIndex] + : 0 + : isBearish + ? basedOnPeak + ? mSamePeakGoldenCount + : basedOnVale + ? valeBuffer[barIndex] + : 0 + : 0; + + // + iRNGBreak.upper = upper; + iRNGBreak.lower = lower; + + // + // Adding POI ... + has = iRNGBreak.IsValid(); + if (has) + { + // + if (isBullish) + { + // + has = AddBoxIfNotExists( + iRNGBreak, + mBullishRangeBreakes // + ); + if (has) + { + // + SortBoxes( + mBullishRangeBreakes, + maxAllowedPOIs // + ); + } + } + else if (isBearish) + { + // + has = AddBoxIfNotExists( + iRNGBreak, + mBearishRangeBreakes // + ); + if (has) + { + // + SortBoxes( + mBearishRangeBreakes, + maxAllowedPOIs // + ); + } + } + } + } + } + + // + if (isPeakSame) + { + // + mSamePeakGoldenCount = + mSamePeakGoldenCount == 0 + ? iBar.GetUp() + : MathMax(mSamePeakGoldenCount, iBar.GetUp()); + mSamePeakCount++; + } + else + { + // + mSamePeakCount = 0; + mSamePeakGoldenCount = 0; + } + + // + if (isValeSame) + { + // + mSameValeGoldenCount = + mSameValeGoldenCount == 0 + ? iBar.GetDown() + : MathMin(mSameValeGoldenCount, iBar.GetDown()); + mSameValeCount++; + } + else + { + // + mSameValeCount = 0; + mSameValeGoldenCount = 0; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + iPBar.Clean(); +} + +/** + * Validate Detected POI(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void ValidatePOIs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int count = 0; + bool has = false; + int barsLength = 3; + datetime to = GetBarTime( + _Symbol, + _Period, + barIndex // + ); + + // + // Liquidities ... + + // + // Bullish Liquidities ... + count = ArraySize(mBullishLiquidities); + has = IsValidSize(count); + if (has) + { + // + ValidateBoxes( + mBullishLiquidities, + barIndex, + barsLength // + ); + } + + // + // Bearish Liquidities ... + count = ArraySize(mBearishLiquidities); + has = IsValidSize(count); + if (has) + { + // + ValidateBoxes( + mBearishLiquidities, + barIndex, + barsLength // + ); + } + + // + // Range Breaks ... + + // + // Bullish ... + count = ArraySize(mBullishRangeBreakes); + has = IsValidSize(count); + if (has) + { + // + ValidateBoxes( + mBullishRangeBreakes, + barIndex, + barsLength // + ); + } + + // + // Bearish ... + count = ArraySize(mBearishRangeBreakes); + has = IsValidSize(count); + if (has) + { + // + ValidateBoxes( + mBearishRangeBreakes, + barIndex, + barsLength // + ); + } + + // +} + +/** + * Draw Detected POI(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DrawPOIs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int count = 0; + XBoxZone iBox; + bool has = false; + datetime to = GetBarTime( + _Symbol, + _Period, + barIndex // + ); + + // + // Liquidities ... + if (mDrawLiquidities) + { + // + count = ArraySize(mBullishLiquidities); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + iBox = mBullishLiquidities[i]; + iBox.to = to; + + // + XCBoxObject *iObj; + has = mDrawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + count = ArraySize(mBearishLiquidities); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + iBox = mBearishLiquidities[i]; + iBox.to = to; + + // + XCBoxObject *iObj; + has = mDrawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + // Range Breaks ... + if (mDrawRangeBreakes) + { + // + // Bullish ... + count = ArraySize(mBullishRangeBreakes); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + iBox = mBullishRangeBreakes[i]; + iBox.to = to; + + // + XCBoxObject *iObj; + has = mDrawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + XPOIStyle iStyle; + iStyle.width = 1; + iStyle.clr = clrAqua; + iStyle.style = STYLE_DOT; + + // + mDrawer.ApplyStyle( + iObj, + iStyle // + ); + + // + mObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // Bearish ... + count = ArraySize(mBearishRangeBreakes); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + iBox = mBearishRangeBreakes[i]; + iBox.to = to; + + // + XCBoxObject *iObj; + has = mDrawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + XPOIStyle iStyle; + iStyle.width = 1; + iStyle.clr = clrMagenta; + iStyle.style = STYLE_DOT; + + // + mDrawer.ApplyStyle( + iObj, + iStyle // + ); + + // + mObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // +} + +/** + * Process Custom Analysing Senarios ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DoProcess( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Some Requirements ... + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Recieve Bar ... + XOHCL iBar; + XOHCL iPBar; + bool has = iBar.Init( + _Symbol, + _Period, + barIndex + // + ); + has = + has && + iBar.GetPreviousBar(iPBar); + if (!has) + { + return; + } + + // + // Do Process ... + + // + // Detecting Trigger Bar ... + + // + bool hasSignal = false; + bool isBullish = false; + bool isBearish = false; + string namePrefix = NULL; + int triggerBarPushers = 0; + ENUM_X_DIRECTION triggerDir; + + // + // Detecting Trigger Bars ... + + // + bool isCond1Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + true, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + bool isCond1BullishTrigger = + isCond1Trigger && + IsBullish(triggerDir); + bool isCond1BearishTrigger = + isCond1Trigger && + IsBearish(triggerDir); + if (isCond1Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond1"; + } + + // + bool isCond2Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + false, // Cond 1 ... + true, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + bool isCond2BullishTrigger = + isCond2Trigger && + IsBullish(triggerDir); + bool isCond2BearishTrigger = + isCond2Trigger && + IsBearish(triggerDir); + if (isCond2Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond2"; + } + + // + bool isCond3Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + false, // Cond 1 ... + false, // Cond 2 ... + true, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + bool isCond3BullishTrigger = + isCond3Trigger && + IsBullish(triggerDir); + bool isCond3BearishTrigger = + isCond3Trigger && + IsBearish(triggerDir); + if (isCond3Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond3"; + } + + // + bool isCond4Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + true, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + bool isCond4BullishTrigger = + isCond4Trigger && + IsBullish(triggerDir); + bool isCond4BearishTrigger = + isCond4Trigger && + IsBearish(triggerDir); + if (isCond4Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond4"; + } + + // + bool isCond5Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + true, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + bool isCond5BullishTrigger = + isCond5Trigger && + IsBullish(triggerDir); + bool isCond5BearishTrigger = + isCond5Trigger && + IsBearish(triggerDir); + if (isCond5Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond5"; + } + + // + bool isCond6Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + true, // Cond 6 ... + false // Cond 7 ... + ); + bool isCond6BullishTrigger = + isCond6Trigger && + IsBullish(triggerDir); + bool isCond6BearishTrigger = + isCond6Trigger && + IsBearish(triggerDir); + if (isCond6Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond6"; + } + + // + bool isCond7Trigger = + mBarAnalyser + .IsValidForTrigger( + iPBar, + triggerDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + true // Cond 7 ... + ); + bool isCond7BullishTrigger = + isCond7Trigger && + IsBullish(triggerDir); + bool isCond7BearishTrigger = + isCond7Trigger && + IsBearish(triggerDir); + if (isCond7Trigger) + { + // + triggerBarPushers++; + namePrefix += "Cond7"; + } + + // + // Summarizing Trigger Bars ... + + // + bool isBullishTriggerBar = + // + isCond1BullishTrigger || + isCond2BullishTrigger || + isCond3BullishTrigger || + isCond4BullishTrigger || + isCond5BullishTrigger || + isCond6BullishTrigger || + isCond7BullishTrigger + // + ; + + // + bool isBearishTriggerBar = + // + isCond1BearishTrigger || + isCond2BearishTrigger || + isCond3BearishTrigger || + isCond4BearishTrigger || + isCond5BearishTrigger || + isCond6BearishTrigger || + isCond7BearishTrigger + // + ; + + // + bool isTriggerBar = + // + triggerBarPushers >= 1 && + (isBullishTriggerBar || + isBearishTriggerBar) + // + ; + + // + // Reading Required Condiions ... + + // + int pIndex = barIndex + 1; + int ppIndex = barIndex + 2; + + // + // PV ... + + // + bool isSamePeak = peakBuffer[pIndex] == peakBuffer[ppIndex]; + bool isSameVale = valeBuffer[pIndex] == valeBuffer[ppIndex]; + + // + bool isPeakOverLast = peakBuffer[pIndex] > peakBuffer[ppIndex]; + bool isPeakUnderLast = peakBuffer[pIndex] < peakBuffer[ppIndex]; + + // + bool isValeOverLast = valeBuffer[pIndex] > valeBuffer[ppIndex]; + bool isValeUnderLast = valeBuffer[pIndex] < valeBuffer[ppIndex]; + + // + bool isSamePeakGolden = peakGoldenBuffer[pIndex] == peakGoldenBuffer[ppIndex]; + bool isSameValeGolden = valeGoldenBuffer[pIndex] == valeGoldenBuffer[ppIndex]; + + // + bool isPeakGoldeOverLast = peakGoldenBuffer[pIndex] > peakGoldenBuffer[ppIndex]; + bool isPeakGoldenUnderLast = peakGoldenBuffer[pIndex] < peakGoldenBuffer[ppIndex]; + + // + bool isValeGoldenOverLast = valeGoldenBuffer[pIndex] > valeGoldenBuffer[ppIndex]; + bool isValeGoldenUnderLast = valeGoldenBuffer[pIndex] < valeGoldenBuffer[ppIndex]; + + // + if (isSamePeak) + { + mSamePeakCount++; + } + else + { + mSamePeakCount = 0; + } + + // + if (isSameVale) + { + mSameValeCount++; + } + else + { + mSameValeCount = 0; + } + + // + if (isSamePeakGolden) + { + mSamePeakGoldenCount++; + } + else + { + mSamePeakGoldenCount = 0; + } + + // + if (isSameValeGolden) + { + mSameValeGoldenCount++; + } + else + { + mSameValeGoldenCount = 0; + } + + // + // SAR ... + + // + bool isSarBullish = sarStateBuffer[pIndex] > 0; + bool isPSarBullish = sarStateBuffer[ppIndex] > 0; + + // + bool isSarBearish = sarStateBuffer[pIndex] < 0; + bool isPSarBearish = sarStateBuffer[ppIndex] < 0; + + // + bool isSarSwitchedToBullish = + isSarBullish && + !isPSarBullish; + + // + bool isSarSwitchedToBearish = + isSarBearish && + !isPSarBearish; + + // + // HKS ... + + // + bool isHKSBullish = hkSBarCloseBuffer[pIndex] > hkSBarOpenBuffer[pIndex]; + bool isPHKSBullish = hkSBarCloseBuffer[ppIndex] > hkSBarOpenBuffer[ppIndex]; + + // + bool isHKSBearish = hkSBarCloseBuffer[pIndex] < hkSBarOpenBuffer[pIndex]; + bool isPHKSBearish = hkSBarCloseBuffer[ppIndex] < hkSBarOpenBuffer[ppIndex]; + + // + bool isHKSSwitchedToBullish = + isHKSBullish && + !isPHKSBullish; + + // + bool isHKSSwitchedToBearish = + isHKSBearish && + !isPHKSBearish; + + // + // SB ... + + // + bool isSBullish = sBarCloseBuffer[pIndex] > sBarOpenBuffer[pIndex]; + bool isPSBullish = sBarCloseBuffer[ppIndex] > sBarOpenBuffer[ppIndex]; + + // + bool isSBearish = sBarCloseBuffer[pIndex] < sBarOpenBuffer[pIndex]; + bool isPSBearish = sBarCloseBuffer[ppIndex] < sBarOpenBuffer[ppIndex]; + + // + bool isSSwitchedToBullish = + isSBullish && + !isPSBullish; + + // + bool isSSwitchedToBearish = + isSBearish && + !isPSBearish; + + // + // KI ... + + // + bool isKIBullish = kiStateBuffer[pIndex] > 0; + bool isPKIBullish = kiStateBuffer[ppIndex] > 0; + + // + bool isKIBearish = kiStateBuffer[pIndex] < 0; + bool isPKIBearish = kiStateBuffer[ppIndex] < 0; + + // + bool isKISwitchedToBullish = + isKIBullish && + !isPKIBullish; + + // + bool isKISwitchedToBearish = + isKIBearish && + !isPKIBearish; + + // + bool isKIBullishBreaked = + iPBar.IsBreaked( + kiBuffer[pIndex], + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_500, + X_BOUNDARY_PRICE_UP_DOWN // + ); + + // + bool isKIBearishBreaked = + iPBar.IsBreaked( + kiBuffer[pIndex], + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_500, + X_BOUNDARY_PRICE_UP_DOWN // + ); + + // + bool isKISame = kiBuffer[pIndex] == kiBuffer[ppIndex]; + bool isKIBullishSame = + isKISame && + isKIBullish; + bool isKIBearishSame = + isKISame && + isKIBearish; + + // + if (isKISame) + { + mSameKICount++; + } + else + { + mSameKICount = 0; + } + + // + if (isKIBullishSame) + { + mSameKIBullishCount++; + } + else + { + mSameKIBullishCount = 0; + } + + // + if (isKIBearishSame) + { + mSameKIBearishCount++; + } + else + { + mSameKIBearishCount = 0; + } + + // + // Validating Trigger Bar based on Conditions ... + if (isTriggerBar) + { + // + // TODO: Remove this if required ... + isTriggerBar = false; + isBullishTriggerBar = false; + isBearishTriggerBar = false; + } + + // + // Detecting Signal ... + + // + // Bullish ... + isBullish = + // + // Conditions Validation ... + isKIBullishBreaked + // isSSwitchedToBullish + // isKISwitchedToBullish + // isSarSwitchedToBullish + // isHKSSwitchedToBullish + // + // Bar Validation ... + // + ; + + // + // Bearish ... + isBearish = + // + // Conditions Validation ... + isKIBearishBreaked + // isSSwitchedToBearish + // isKISwitchedToBearish + // isSarSwitchedToBearish + // isHKSSwitchedToBearish + // + // Bar Validation ... + // + ; + + // + // Summarizing Signal ... + hasSignal = + isBullish || + isBearish; + + // + // Draw Requirements ... + + // + // Draw Trigger Bar ... + if (isTriggerBar) + { + // + int triggerBullishArrowCode = 225; + int triggerBearishArrowCode = 226; + + // + color triggerBarBullishColor = clrLime; + color triggerBarBearishColor = clrRed; + + // + ENUM_ARROW_ANCHOR triggerBullishAnchor = ANCHOR_TOP; + ENUM_ARROW_ANCHOR triggerBearishAnchor = ANCHOR_BOTTOM; + + // + int arrowWidth = 3; + int arrowCode = + isBullishTriggerBar + ? triggerBullishArrowCode + : triggerBearishArrowCode; + ENUM_X_PRICE arrowPriceType = + isBullishTriggerBar + ? X_PRICE_LOW + : X_PRICE_HIGH; + color arrowColor = + isBullishTriggerBar + ? triggerBarBullishColor + : triggerBarBearishColor; + ENUM_ARROW_ANCHOR arrowAnchor = + isBullishTriggerBar + ? triggerBullishAnchor + : triggerBearishAnchor; + + // + XCBarArrowObject *iObj; + has = mDrawer.CreateBarArrow( + iBar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + namePrefix // + ); + if (has) + { + mObjects.Add(iObj); + } + + // + // Converts to Box ... + XBoxZone iBox; + iBox.type = "XTRB"; + iBox.to = iBar.time; + iBox.symbol = _Symbol; + iBox.period = _Period; + iBox.lower = iPBar.low; + iBox.from = iPBar.time; + iBox.upper = iPBar.high; + iBox.dir = + isBullishTriggerBar + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + if (iBox.IsValid()) + { + // + // XCBoxObject *iObj; + // has = mDrawer.DrawBox( + // iBox, + // iObj // + // ); + // if (has) + // { + // mObjects.Add(iObj); + // } + + // + XSignal iSignal; + double iRewardRatios[] = { + 1, + 1.5, + 2 // + }; + has = ToSignal( + iBox, + iSignal, + iRewardRatios, + 0 // Additional SL ... + ); + if (has) + { + // + XCSignalObject *iObj; + has = mDrawer.DrawSignal( + iSignal, + iObj, + 4 // + ); + if (has) + { + mObjects.Add(iObj); + } + } + } + + // + } + + // + // Draw Signal ... + if (hasSignal) + { + // + int bullishArrowCode = 225; + int bearishArrowCode = 226; + + // + color bullishColor = clrLime; + color bearishColor = clrRed; + + // + ENUM_ARROW_ANCHOR bullishAnchor = ANCHOR_TOP; + ENUM_ARROW_ANCHOR bearishAnchor = ANCHOR_BOTTOM; + + // + int arrowWidth = 3; + int arrowCode = + isBullish + ? bullishArrowCode + : bearishArrowCode; + ENUM_X_PRICE arrowPriceType = + isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + color arrowColor = + isBullish + ? bullishColor + : bearishColor; + ENUM_ARROW_ANCHOR arrowAnchor = + isBullish + ? bullishAnchor + : bearishAnchor; + + // + XCBarArrowObject *iObj; + has = mDrawer.CreateBarArrow( + iBar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + namePrefix // + ); + if (has) + { + mObjects.Add(iObj); + } + + // + // Converts to Box ... + XBoxZone iBox; + iBox.type = "XSG"; + iBox.to = iBar.time; + iBox.symbol = _Symbol; + iBox.period = _Period; + iBox.lower = iPBar.low; + iBox.from = iPBar.time; + iBox.upper = iPBar.high; + iBox.dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + if (iBox.IsValid()) + { + // + XSignal iSignal; + double iRewardRatios[] = { + 1, + 1.5, + 2 // + }; + has = ToSignal( + iBox, + iSignal, + iRewardRatios, + 0 // Additional SL ... + ); + if (has) + { + // + XCSignalObject *iObj; + has = mDrawer.DrawSignal( + iSignal, + iObj, + 4 // + ); + if (has) + { + mObjects.Add(iObj); + } + } + } + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + iPBar.Clean(); +} + +//////////////////////////////////////////////////////////////////// + diff --git a/BKPS/14040626/Documents/BKP/tmp.poi.mq5 b/BKPS/14040626/Documents/BKP/tmp.poi.mq5 new file mode 100644 index 0000000..db780f8 --- /dev/null +++ b/BKPS/14040626/Documents/BKP/tmp.poi.mq5 @@ -0,0 +1,7058 @@ +// +// All Available POI(s) ... +enum ENUM_XPOIS +{ + // + X_POI_NONE, + // + X_POI_TICKS_ZONES, // Ticks Zone ... + // + // Trading Day ... + X_POI_TRADING_DAY, // Trading Day ... + // + // Market Session ... + X_POI_MARKET_SESSION, // Market Session ... + // + // Momentum Bar ... + X_POI_MOMENTUM_BAR, // Momentum Bar ... + // + // Rejection Bar ... + X_POI_REJECTION_BAR, // Rejection Bar ... + // + // Swings ... + X_POI_SWING_HIGH, // Simple Swing High ... + X_POI_SWING_LOW, // Simple Swing Low ... + // + // Support nad Resistance ... + X_POI_SUPPORT_ZONE, // Support Zone ... + X_POI_RESISTANCE_ZONE, // Resistance Zone ... + // + // Supply and Demand Zones ... + X_POI_SUPPLY_ZONE, // Supply Zone ... + X_POI_DEMAND_ZONE, // Demand Zone ... + // + // Order Blocks ... + X_POI_BULLISH_ORDERBLOCK, // Bullish Order Block ... + X_POI_BEARISH_ORDERBLOCK, // Bearish Order Block ... + // + // Fair Value Gaps ... + X_POI_BULLISH_FVG, // Bullish Order Block ... + X_POI_BEARISH_FVG, // Bearish Order Block ... + // + X_BULLISH_CONSOLIDATION_ZONE, + X_BEARISH_CONSOLIDATION_ZONE, + // + X_BULLISH_SHARP, + X_BEARISH_SHARP, + // + X_BULLISH_SPIKE, + X_BEARISH_SPIKE, + // + X_BULLISH_PULLBACK, + X_BEARISH_PULLBACK, +}; + +// +// Event Types ... +enum ENUM_XPOI_EVENTS +{ + // + X_POI_EVENT_NONE, + // + // Trading Days ... + X_TRADE_DAY_FIRST_BAR, // Trading Day First Bar ... + X_TRADE_DAY_LAST_BAR, // Trading Day Last Bar ... + // + // Session ... + X_SESSION_FIRST_BAR, // Session First Bar ... + X_SESSION_LAST_BAR, // Session Last Bar ... + // + // Momentum Bar ... + X_BULLISH_MOMENTUM_BAR_DETECTED, + X_BEARISH_MOMENTUM_BAR_DETECTED, + // + // Rejection Bar ... + X_BULLISH_REJECTION_BAR_DETECTED, + X_BEARISH_REJECTION_BAR_DETECTED, + // + // Swings ... + X_SWING_HIGH_DETECTED, + X_SWING_LOW_DETECTED, + // + // Support nad Resistance ... + X_SUPPORT_ZONE_DETECTED, // Support Zone ... + X_RESISTANCE_ZONE_DETECTED, // Resistance Zone ... + // + // Supply nad Demand ... + X_SUPPLY_ZONE_DETECTED, // Supply Zone ... + X_DEMAND_ZONE_DETECTED, // Demand Zone ... + // + // Order Blocks ... + X_BULLISH_ORDERBLOCK_DETECTED, // Bullish Order Block ... + X_BEARISH_ORDERBLOCK_DETECTED, // Bearish Order Block ... + // + // Fair Value Gaps ... + X_BULLISH_FVG_DETECTED, // Bullish Fair Value GapÙ‘ ... + X_BEARISH_FVG_DETECTED, // Bearish Fair Value GapÙ‘ ... + X_BULLISH_CONSOLIDATION_ZONE_DETECTED, + X_BEARISH_CONSOLIDATION_ZONE_DETECTED, + X_BULLISH_SHARP_DETECTED, + X_BEARISH_SHARP_DETECTED, + X_BULLISH_SPIKE_DETECTED, + X_BEARISH_SPIKE_DETECTED, + X_BULLISH_PULLBACK_DETECTED, + X_BEARISH_PULLBACK_DETECTED, +}; + +// +enum ENUM_XZONE_STATE +{ + XZONE_STATE_NONE, + XZONE_STATE_PASSED, + XZONE_STATE_FAILED, + XZONE_STATE_IGNORED, +}; + +// +// Forext Sessions ... +enum ENUM_XSESSION +{ + X_TOKYO, + X_SYDNEY, + X_LONDON, + X_NEW_YORK, + X_FRANKFORT, +}; + +/** + * Converts ENUM_XPOI value to String Representation ... + * + * @param value: ENUM_XPOI member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOIS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POI_TRADING_DAY: + result = "XTDAY"; + break; + + // + case X_POI_MARKET_SESSION: + result = "XMSESS"; + break; + + // + case X_POI_MOMENTUM_BAR: + result = "XMNTMB"; + break; + + // + case X_POI_REJECTION_BAR: + result = "XRJCTB"; + break; + + // + case X_POI_SWING_HIGH: + result = "XSPH"; + break; + + // + case X_POI_SWING_LOW: + result = "XSPL"; + break; + + // + case X_POI_SUPPORT_ZONE: + result = "XSUP"; + break; + + // + case X_POI_RESISTANCE_ZONE: + result = "XRES"; + break; + + // + case X_POI_SUPPLY_ZONE: + result = "XSUPPLY"; + break; + + // + case X_POI_DEMAND_ZONE: + result = "XDEMAND"; + break; + + // + case X_POI_BULLISH_ORDERBLOCK: + result = "XBULLOB"; + break; + + // + case X_POI_BEARISH_ORDERBLOCK: + result = "XBEAROB"; + break; + + // + case X_POI_BULLISH_FVG: + result = "XBULLFVG"; + break; + + // + case X_POI_BEARISH_FVG: + result = "XBEARFVG"; + break; + + // + case X_POI_TICKS_ZONES: + result = "XTKSZ"; + break; + + // + case X_BULLISH_CONSOLIDATION_ZONE: + result = "XBULLCZ"; + break; + + // + case X_BEARISH_CONSOLIDATION_ZONE: + result = "XBEARCZ"; + break; + + // + case X_BULLISH_SPIKE: + result = "XBULLSPK"; + break; + + // + case X_BEARISH_SPIKE: + result = "XBEARSPK"; + break; + } + + // + return result; +} + +/** + * Converts ENUM_XSESSION value to String Representation ... + * + * @param value: ENUM_XSESSION member ... + * + * @return ( string ) + */ +string ToString(ENUM_XSESSION value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SYDNEY: + result = "Sydney"; + break; + + // + case X_TOKYO: + result = "Tokyo"; + break; + + // + case X_FRANKFORT: + result = "FrankGurt"; + break; + + // + case X_LONDON: + result = "London"; + break; + + // + case X_NEW_YORK: + result = "NewYork"; + break; + } + + // + return result; +} + +/** + * Generate General Event Messages ... + * + * @param value: ENUM_XPOI_EVENTS member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOI_EVENTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_TRADE_DAY_FIRST_BAR: + result = "First Bar of Day"; + break; + + // + case X_TRADE_DAY_LAST_BAR: + result = "Last Bar of Day"; + break; + + // + case X_SESSION_FIRST_BAR: + result = "First Bar of Session"; + break; + + // + case X_SESSION_LAST_BAR: + result = "Last Bar of Session"; + break; + + // + case X_BULLISH_MOMENTUM_BAR_DETECTED: + result = "Bullish Momentum Bar Detected"; + break; + + // + case X_BEARISH_MOMENTUM_BAR_DETECTED: + result = "Bearish Momentum Bar Detected"; + break; + + // + case X_BULLISH_REJECTION_BAR_DETECTED: + result = "Bullish Rejection Bar Detected"; + break; + + // + case X_BEARISH_REJECTION_BAR_DETECTED: + result = "Bearish Rejection Bar Detected"; + break; + + // + case X_SWING_HIGH_DETECTED: + result = "Swing High Detected"; + break; + + // + case X_SWING_LOW_DETECTED: + result = "Swing Low Detected"; + break; + + // + case X_SUPPORT_ZONE_DETECTED: + result = "Support Zone Detected"; + break; + + // + case X_RESISTANCE_ZONE_DETECTED: + result = "Resistance Zone Detected"; + break; + + // + case X_SUPPLY_ZONE_DETECTED: + result = "Supply Zone Detected"; + break; + + // + case X_DEMAND_ZONE_DETECTED: + result = "Demand Zone Detected"; + break; + + // + case X_BULLISH_ORDERBLOCK_DETECTED: + result = "Bullish Order Block Detected"; + break; + + // + case X_BEARISH_ORDERBLOCK_DETECTED: + result = "Bearish Orer Block Detected"; + break; + + // + case X_BULLISH_FVG_DETECTED: + result = "Bullish FVG Detected"; + break; + + // + case X_BEARISH_FVG_DETECTED: + result = "Bearish FVg Detected"; + break; + } + + // + return result; +} + +// +// Implementation ... + +// +// Base POI Model Class ... +class XCBasePOI : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCBasePOI() + { + // + Clean(); + + // + mSep = "_"; + mLineSep = "\n"; + } + + // + // Deconstructor ... + void ~XCBasePOI() + { + Clean(); + } + + // + // Virtual ... + + /** + * Cleanup ... + */ + virtual void Clean() + { + mType = X_POI_NONE; + } + + /** + * Validate ... + * + * @return ( virtual bool ) + */ + virtual bool IsValid() + { + return false; + } + + /** + * Retrieve POI Type ... + * + * @return ( virtual ENUM_XPOIS member ) + */ + virtual ENUM_XPOIS Type() + { + return mType; + } + + /** + * Retrieve POI Type ... + * + * @return ( virtual string ) + */ + virtual string TypeAsString() + { + return ToString(mType); + } + + /** + * Retrieve POI Tag ... + * + * @return ( virtual string ) + */ + virtual string GetTag() + { + return NULL; + } + + /** + * Retrieve POI Tooltip ... + * + * @return ( virtual string ) + */ + virtual string GetTooltip() + { + return NULL; + } + + // + protected: + // + // Props ... + string mSep; // Separator ... + string mLineSep; // Line Separator ... + ENUM_XPOIS mType; // Type ... + + // + private: + // +}; + +// +typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, + XCBasePOI *param // +); + +// +// Zone POI Class ... +class XCZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCZone() + { + } + + // + // Deconstructor ... + void ~XCZone() + { + } + + // + // Tools ... + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Upper Boundary ... + * + * @return ( double ) + */ + double Upper() + { + return mUpper; + } + + /** + * Set Zone Upper Boundary ... + */ + void Upper(double value) + { + mUpper = value; + } + + /** + * Get Zone Lower Boundary ... + * + * @return ( double ) + */ + double Lower() + { + return mLower; + } + + /** + * Set Zone Lower Boundary ... + */ + void Lower(double value) + { + mLower = value; + } + + /** + * Retrieve Zone Range ... + * + * @return ( double ) + */ + double Range() + { + // + double result = 0; + + // + double upper = Upper(); + double lower = Lower(); + + // + if (upper > 0 && lower > 0 && upper > lower) + { + result = upper - lower; + } + + // + return result; + } + + double RangePercent() + { + // + double result = 0; + + // + double range = Range(); + if (range > 0) + { + result = range / 100; + } + + // + return result; + } + + // + // Virtuals ... + + /** + * Get Zone Start Date ... + * + * @return ( virtual datetime ) + */ + virtual datetime From() + { + return NULL; + } + + /** + * Get Zone End Date ... + * + * @return ( virtual datetime ) + */ + virtual datetime To() + { + return NULL; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + // Validators ... + + /** + * Validate Upper and Lower of Zone ... + * + * @return ( bool ) + */ + bool IsValidBoundary() + { + // + bool result = false; + + // + result = + // + mUpper > 0 && + mLower > 0 && + mUpper >= mLower + // + ; + + // + return result; + } + + /** + * Check From Date of Zone is Valid ... + * + * @return ( bool ) + */ + bool IsValidFrom() + { + // + bool result = false; + + // + datetime from = From(); + result = IsSpecifiedValid(from); + + // + return result; + } + + // + protected: + // + // Props ... + double mUpper; // Zone Upper ... + double mLower; // Zone Lower ... + + // + private: + // + // Props ... + + // +}; + +// +// From To Zone ... +class XCFromToZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCFromToZone() + { + } + + // + // Deconstructor ... + void ~XCFromToZone() + { + } + + // + // Tools ... + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from // + ) + { + // + bool result = false; + + // + result = type != X_POI_NONE && + IsSpecifiedValid(from) && + IsSpecifiedValid(title); + + // + mType = type; + mFrom = from; + mTitle = title; + mTo = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from, + datetime to // + ) + { + // + bool result = false; + + // + result = IsValid(); + + // + result = InitFromTo( + type, + title, + from // + ); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + mTo = to; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Start Time ... + * + * @return ( datetime ) + */ + datetime From() + { + return mFrom; + } + + /** + * Set Zone Start Time ... + * + * @param value: Datetime + */ + void From(datetime value) + { + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Get Zone End Time ... + * + * @return ( datetime ) + */ + datetime To() + { + return mTo; + } + + /** + * Set Zone End Time ... + * + * @param value: Datetime + */ + void To(datetime value) + { + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Get Title ... + * + * @return ( string ) + */ + string Title() + { + return mTitle; + } + + /** + * Set Title ... + * + * @param value: String ... + */ + // void Title(string value) + // { + // mTitle = value; + // } + + // + // Overrides ... + + void Clean() override + { + // + mTo = NULL; + mFrom = NULL; + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = + // + mType != X_POI_NONE && + IsSpecifiedValid(mTo) && + IsSpecifiedValid(mFrom) && + IsSpecifiedValid(mTitle) + // + ; + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = TypeAsString() + mSep + ToString(From()) + mSep + Title(); + hash = ToMD5(hash); + + // + result = TypeAsString() + "[" + Title() + "]" + mSep + hash; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + datetime mFrom; // Start Date + datetime mTo; // End Date + string mTitle; // Zone Title + + // +}; + +// +// Bar Zone ... +class XCBarZone : public XCZone +{ + // + public: + // + + // + // Constructor ... + void XCBarZone() + { + } + + // + // Deconstructor ... + void ~XCBarZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * @param upperPrice: ENUM_X_PRICE member ... + * @param lowerPrice: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ + bool InitBarZone( + XOHCL &bar, + ENUM_XPOIS type, + ENUM_X_PRICE upperPrice, + ENUM_X_PRICE lowerPrice // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + type != X_POI_NONE && + upperPrice != lowerPrice; + if (!result) + { + return result; + } + + // + mBar = bar; + mType = type; + mUpperPrice = upperPrice; + mLowerPrice = lowerPrice; + mUpper = bar.GetPrice(upperPrice); + mLower = bar.GetPrice(lowerPrice); + + // + result = IsValidBarZone(); + if (result) + { + // + From(bar.time); + To(TimeCurrent()); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Fill Bar as XOHCL struct ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bar = mBar; + result = mBar.IsValid(); + + // + return result; + } + + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Retrieve Bar Time ... + * + * @return ( datetime ) + */ + datetime BarTime() + { + return mBar.time; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + if (!mBar.IsValid()) + { + return result; + } + + // + return mBar.symbol; + + // + return result; + } + + /** + * Get Period ... + * + * @return ( int ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + if (!mBar.IsValid()) + { + return result; + } + + // + return mBar.period; + + // + return result; + } + + /** + * Check Zone Started or not ... + * First Exit in Direction of Zone after From ... + * + * @param forDir: exit direction ... + * @param startedBar: specified Start Bar ... + * @param isBodyOut: specified Start Bar Close is Out of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsStarted( + ENUM_X_DIRECTION forDir, + XOHCL &startedBar, + bool &isBodyOut, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + startedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + // Detect From Bar Index ... + int fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + startedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = startedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? startedBar.IsBullish() && + startedBar.GetUp() > Upper() + : startedBar.IsBearish() && + startedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check Zone Activated or not ... + * First Enter in Opposit Direction of Zone after Start ... + * + * @param forDir: exit direction ... + * @param activatedBar: specified Activation Bar ... + * @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsActivated( + ENUM_X_DIRECTION forDir, + XOHCL &activatedBar, + bool &isBodyIn, + bool forceBodyOutStarted = true, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyIn = false; + activatedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + result = + !forceBodyOutStarted + ? isStarted + : isStarted && + isBodyOut; + if (!result) + { + // + startedBar.Clean(); + return result; + } + + // + int fromIndex = startedBar.Index() - 1; + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isInsideFromUpper = + // + iBar.high < Upper() || + (iBar.high > Upper() && + iBar.low <= Upper() && + iBar.close <= Upper()) + // + ; + + // + bool isInsideFromLower = + // + iBar.low > Lower() || + (iBar.low < Lower() && + iBar.high >= Lower() && + iBar.close >= Lower()) + // + ; + + // + bool isInside = + isInsideFromUpper || + isInsideFromLower; + if (isInside) + { + // + result = isInside && + isBullish + ? isInsideFromUpper + : isInsideFromLower; + if (result) + { + // + activatedBar = iBar; + iBar.Clean(); + startedBar.Clean(); + break; + } + } + + // + iBar.Clean(); + startedBar.Clean(); + } + + // + result = activatedBar.IsValid(); + if (result) + { + // + isBodyIn = + isBullish + ? activatedBar.IsBearish() && + activatedBar.GetDown() < Upper() + : activatedBar.IsBullish() && + activatedBar.GetUp() > Lower(); + } + + // + return result; + } + + /** + * Check Zone Breaked or not ... + * + * @param forDir: exit direction ... + * @param breakedBar: specified Breaked Bar ... + * @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ... + * @param ignoreStart: Ignore Zone Start (Calculate from From()) ... + * @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsBreaked( + ENUM_X_DIRECTION forDir, + XOHCL &breakedBar, + bool &isBodyOut, + bool ignoreStart = false, + bool startedBodyOut = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + breakedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreStart) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + + // + bool isStartPassed = + !startedBodyOut + ? isStarted + : isStarted && + isBodyOut; + if (isStartPassed) + { + fromIndex = startedBar.Index() - 1; + } + + // + startedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + (isBullish + ? isBreakedFromLower + : isBreakedFromUpper); + if (result) + { + // + breakedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = breakedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? breakedBar.IsBearish() && + breakedBar.GetDown() < Lower() + : breakedBar.IsBullish() && + breakedBar.GetUp() > Upper(); + } + + // + return result; + } + + /** + * Check Zone Worked or not ... + * + * @param forDir: exit direction ... + * @param workedBar: specified Worked Bar ... + * @param isBodyOut: specified Worked Bar Close is Out of Zone or not ... + * @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ... + * @param activationStartedOut: Specified Zone Start Bar State ... + * @param activationBodyIn: Specified Zone Activation Bar State ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsWorked( + ENUM_X_DIRECTION forDir, + XOHCL &workedBar, + bool &isBodyOut, + bool ignoreActivation = false, + bool activationStartedOut = false, + bool activationBodyIn = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + workedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreActivation) + { + // + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = IsActivated( + forDir, + activatedBar, + isBodyIn, + activationStartedOut, + forPeriod // + ); + + // + bool isActivationPassed = + !activationBodyIn + ? isActivated + : isActivated && + isBodyIn; + if (isActivationPassed) + { + fromIndex = activatedBar.Index() - 1; + } + + // + activatedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + workedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = workedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? workedBar.IsBullish() && + workedBar.GetUp() > Upper() + : workedBar.IsBearish() && + workedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mBar.Clean(); + mUpper = 0; + mLower = 0; + mType = X_POI_NONE; + } + + datetime From() override + { + return mFrom; + } + + datetime To() override + { + return mTo; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValidBarZone()) + { + return result; + } + + // + string hash = ToMD5(mBar.GetTag()); + + // + result = + // + TypeAsString() + mSep + + ToString(mBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValidBarZone()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mBar; // Bar ... + ENUM_X_PRICE mUpperPrice; // Upper Price Selection + ENUM_X_PRICE mLowerPrice; // Lower Price Selection + + /** + * Check Bar Zone Validation ... + * + * @return ( bool ) + */ + bool IsValidBarZone() + { + // + bool result = false; + + // + result = mBar.IsValid() && + mType != X_POI_NONE && + IsValidBoundary(); + + // + return result; + } + + // + private: + // + // Props ... + datetime mFrom; + datetime mTo; + + // +}; +class XCTwoBarZone : public XCZone +{ + // + public: + // + + // + // Constructor ... + void XCTwoBarZone() + { + } + + // + // Deconstructor ... + void ~XCTwoBarZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * @param upperPrice: ENUM_X_PRICE member ... + * @param lowerPrice: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ + bool InitTwoBarZone( + XOHCL &startBar, + XOHCL &endBar, + ENUM_XPOIS type, + ENUM_X_PRICE startPrice, + ENUM_X_PRICE endPrice // + ) + { + // + bool result = false; + + // + result = startBar.IsValid() && + endBar.IsValid() && + startBar.symbol == endBar.symbol && + startBar.period == endBar.period && + startBar.time < endBar.time && + type != X_POI_NONE; + if (!result) + { + return result; + } + + // + mType = type; + mEndBar = endBar; + mStartBar = startBar; + + // + int startIndex = startBar.Index(); + int endIndex = endBar.Index(); + + // + double mStartPrice = startBar.GetPrice(startPrice); + double mEndPrice = endBar.GetPrice(endPrice); + bool isStartOverEnd = mStartPrice > mEndPrice; + + // + if (isStartOverEnd) + { + // + mUpperPrice = startPrice; + mLowerPrice = endPrice; + } + else + { + // + mUpperPrice = endPrice; + mLowerPrice = startPrice; + } + + // + mUpper = MathMax(mStartPrice, mEndPrice); + mLower = MathMin(mStartPrice, mEndPrice); + + // + result = IsValidTwoBarZone(); + if (result) + { + // + From(startBar.time); + To(endBar.time); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidTwoBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidTwoBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Fill Start Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillStartBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bar = mStartBar; + + // + return result; + } + + /** + * Fill End Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillEndBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bar = mEndBar; + + // + return result; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + if (!mStartBar.IsValid()) + { + return result; + } + + // + return mStartBar.symbol; + + // + return result; + } + + /** + * Get Period ... + * + * @return ( int ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + if (!mStartBar.IsValid()) + { + return result; + } + + // + return mStartBar.period; + + // + return result; + } + + /** + * Check Zone Started or not ... + * First Exit in Direction of Zone after From ... + * + * @param forDir: exit direction ... + * @param startedBar: specified Start Bar ... + * @param isBodyOut: specified Start Bar Close is Out of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsStarted( + ENUM_X_DIRECTION forDir, + XOHCL &startedBar, + bool &isBodyOut, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + startedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + // Detect From Bar Index ... + int fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + startedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = startedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? startedBar.IsBullish() && + startedBar.GetUp() > Upper() + : startedBar.IsBearish() && + startedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check Zone Activated or not ... + * First Enter in Opposit Direction of Zone after Start ... + * + * @param forDir: exit direction ... + * @param activatedBar: specified Activation Bar ... + * @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsActivated( + ENUM_X_DIRECTION forDir, + XOHCL &activatedBar, + bool &isBodyIn, + bool forceBodyOutStarted = true, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyIn = false; + activatedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + result = + !forceBodyOutStarted + ? isStarted + : isStarted && + isBodyOut; + if (!result) + { + // + startedBar.Clean(); + return result; + } + + // + int fromIndex = startedBar.Index() - 1; + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isInsideFromUpper = + // + iBar.high < Upper() || + (iBar.high > Upper() && + iBar.low <= Upper() && + iBar.close <= Upper()) + // + ; + + // + bool isInsideFromLower = + // + iBar.low > Lower() || + (iBar.low < Lower() && + iBar.high >= Lower() && + iBar.close >= Lower()) + // + ; + + // + bool isInside = + isInsideFromUpper || + isInsideFromLower; + if (isInside) + { + // + result = isInside && + isBullish + ? isInsideFromUpper + : isInsideFromLower; + if (result) + { + // + activatedBar = iBar; + iBar.Clean(); + startedBar.Clean(); + break; + } + } + + // + iBar.Clean(); + startedBar.Clean(); + } + + // + result = activatedBar.IsValid(); + if (result) + { + // + isBodyIn = + isBullish + ? activatedBar.IsBearish() && + activatedBar.GetDown() < Upper() + : activatedBar.IsBullish() && + activatedBar.GetUp() > Lower(); + } + + // + return result; + } + + /** + * Check Zone reaked or not ... + * + * @param forDir: exit direction ... + * @param breakedBar: specified Breaked Bar ... + * @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ... + * @param ignoreStart: Ignore Zone Start (Calculate from From()) ... + * @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsBreaked( + ENUM_X_DIRECTION forDir, + XOHCL &breakedBar, + bool &isBodyOut, + bool ignoreStart = false, + bool startedBodyOut = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + breakedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreStart) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + + // + bool isStartPassed = + !startedBodyOut + ? isStarted + : isStarted && + isBodyOut; + if (isStartPassed) + { + fromIndex = startedBar.Index() - 1; + } + + // + startedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + (isBullish + ? isBreakedFromLower + : isBreakedFromUpper); + if (result) + { + // + breakedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = breakedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? breakedBar.IsBearish() && + breakedBar.GetDown() < Lower() + : breakedBar.IsBullish() && + breakedBar.GetUp() > Upper(); + } + + // + return result; + } + + /** + * Check Zone Worked or not ... + * + * @param forDir: exit direction ... + * @param workedBar: specified Worked Bar ... + * @param isBodyOut: specified Worked Bar Close is Out of Zone or not ... + * @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ... + * @param activationStartedOut: Specified Zone Start Bar State ... + * @param activationBodyIn: Specified Zone Activation Bar State ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsWorked( + ENUM_X_DIRECTION forDir, + XOHCL &workedBar, + bool &isBodyOut, + bool ignoreActivation = false, + bool activationStartedOut = false, + bool activationBodyIn = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + workedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreActivation) + { + // + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = IsActivated( + forDir, + activatedBar, + isBodyIn, + activationStartedOut, + forPeriod // + ); + + // + bool isActivationPassed = + !activationBodyIn + ? isActivated + : isActivated && + isBodyIn; + if (isActivationPassed) + { + fromIndex = activatedBar.Index() - 1; + } + + // + activatedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + workedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = workedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? workedBar.IsBullish() && + workedBar.GetUp() > Upper() + : workedBar.IsBearish() && + workedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mStartBar.Clean(); + mEndBar.Clean(); + mUpper = 0; + mLower = 0; + mUseStartBarForUpper = false; + mType = X_POI_NONE; + } + + datetime From() override + { + return mFrom; + } + + datetime To() override + { + return mTo; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValidTwoBarZone()) + { + return result; + } + + // + string hash = ToMD5(mStartBar.GetTag() + mSep + mEndBar.GetTag()); + + // + result = + // + TypeAsString() + mSep + + ToString(mStartBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValidTwoBarZone()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mStartBar; // Start (Oldest) Bar ... + XOHCL mEndBar; // End (Newest) Bar ... + bool mUseStartBarForUpper; // Use Start Bar for Upper Calculation ... + ENUM_X_PRICE mUpperPrice; // Upper Price Selection + ENUM_X_PRICE mLowerPrice; // Lower Price Selection + + /** + * Check Two Bar Zone Validation ... + * + * @return ( bool ) + */ + bool IsValidTwoBarZone() + { + // + bool result = false; + + // + result = mStartBar.IsValid() && + mEndBar.IsValid() && + mStartBar.symbol == mEndBar.symbol && + mStartBar.period == mEndBar.period && + mStartBar.time < mEndBar.time && + mType != X_POI_NONE && + IsValidBoundary(); + + // + return result; + } + + // + private: + // + // Props ... + datetime mFrom; + datetime mTo; + + // +}; + +// +// Swing Class ... +class XCSwing : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCSwing() + { + } + + // + // Deconstructor ... + void ~XCSwing() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + ENUM_XPOIS type // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + (type == X_POI_SWING_HIGH || + type == X_POI_SWING_LOW); + if (!result) + { + return result; + } + + // + mBar = bar; + mType = type; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Fill Bar as XOHCL struct ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bar = mBar; + result = mBar.IsValid(); + + // + return result; + } + + /** + * Get Time of Swing ... + * + * @return ( datetime ) + */ + datetime GetTime() + { + // + datetime result = NULL; + + // + if (!IsValid() || !mBar.IsValid()) + { + return result; + } + + // + result = mBar.time; + + // + return result; + } + + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOHCL bar; + bool isFilled = FillBar(bar); + if (!isFilled) + { + return result; + } + + // + result = bar.period; + + // + return result; + } + + /** + * Check Swing High or not ... + * + * @return ( bool ) + */ + bool IsSwingHigh() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + Type() == X_POI_SWING_HIGH; + + // + return result; + } + + /** + * Check Swing Low or not ... + * + * @return ( bool ) + */ + bool IsSwingLow() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + Type() == X_POI_SWING_LOW; + + // + return result; + } + + /** + * Get Swing Value ... + * + * @return ( double ) + */ + double GetValue() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsSwingHigh() + ? mBar.high + : mBar.low; + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mBar.Clean(); + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = mBar.IsValid() && + (mType == X_POI_SWING_HIGH || + mType == X_POI_SWING_LOW); + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = ToMD5(mBar.GetTag()); + + // + string subType = IsSwingHigh() + ? "High" + : "Low"; + + // + result = + // + TypeAsString() + mSep + + subType + mSep + + ToString(mBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mBar; // Swing Bar ... + + // + private: + // +}; + +// +// Supply Zone ... +class XCSupplyZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCSupplyZone() + { + } + + // + // Deconstructor ... + void ~XCSupplyZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_SUPPLY_ZONE, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_SUPPLY_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Demand Zone ... +class XCDemandZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCDemandZone() + { + } + + // + // Deconstructor ... + void ~XCDemandZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_DEMAND_ZONE, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_DEMAND_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Support Zone ... +class XCSupportZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCSupportZone() + { + } + + // + // Deconstructor ... + void ~XCSupportZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_SUPPORT_ZONE, + X_PRICE_DOWN, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_SUPPORT_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Resistance Zone ... +class XCResistanceZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCResistanceZone() + { + } + + // + // Deconstructor ... + void ~XCResistanceZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_RESISTANCE_ZONE, + X_PRICE_HIGH, + X_PRICE_UP // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_RESISTANCE_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Order Block ... +class XCOrderBlock : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCOrderBlock() + { + } + + // + // Deconstructor ... + void ~XCOrderBlock() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + ENUM_XPOIS mTT = + IsSpecifiedBullish(dir) + ? X_POI_BULLISH_ORDERBLOCK + : X_POI_BEARISH_ORDERBLOCK; + + // + result = InitBarZone( + bar, + mTT, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BULLISH_ORDERBLOCK; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_ORDERBLOCK; + + // + return result; + } + + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + (mType == X_POI_BULLISH_ORDERBLOCK || + mType == X_POI_BEARISH_ORDERBLOCK); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Rejection Bar ... +class XCRejectionBar : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCRejectionBar() + { + } + + // + // Deconstructor ... + void ~XCRejectionBar() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = + bar.GetLowShadow() > bar.GetHighShadow(); + bool isBearish = + bar.GetHighShadow() > bar.GetLowShadow(); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + ENUM_X_PRICE upPrice = isBullish + ? X_PRICE_HIGH + : X_PRICE_DOWN; + // + ENUM_X_PRICE loPrice = isBullish + ? X_PRICE_UP + : X_PRICE_LOW; + + // + result = InitBarZone( + bar, + X_POI_REJECTION_BAR, + upPrice, + loPrice // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_REJECTION_BAR && + mBar.GetLowShadow() > mBar.GetHighShadow(); + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_REJECTION_BAR && + mBar.GetHighShadow() > mBar.GetLowShadow(); + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_REJECTION_BAR; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Momentum Bar ... +class XCMomentumBar : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCMomentumBar() + { + } + + // + // Deconstructor ... + void ~XCMomentumBar() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = bar.IsBullish(); + bool isBearish = bar.IsBearish(); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_MOMENTUM_BAR, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + mBar.IsBullish() && + Type() == X_POI_MOMENTUM_BAR; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + mBar.IsBearish() && + Type() == X_POI_MOMENTUM_BAR; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_MOMENTUM_BAR; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Fair Value Gap ... +class XCFVG : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCFVG() + { + } + + // + // Deconstructor ... + void ~XCFVG() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + bool isDirBullish = IsSpecifiedBullish(dir); + ENUM_XPOIS mTT = + isDirBullish + ? X_POI_BULLISH_FVG + : X_POI_BEARISH_FVG; + + // + ENUM_X_PRICE startPrice = isDirBullish + ? X_PRICE_HIGH + : X_PRICE_LOW; + ENUM_X_PRICE endPrice = isDirBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = InitTwoBarZone( + startBar, + endBar, + mTT, + startPrice, + endPrice // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BULLISH_FVG; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_FVG; + + // + return result; + } + + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidTwoBarZone() && + (mType == X_POI_BULLISH_FVG || + mType == X_POI_BEARISH_FVG); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Ticks Zones ... + +// +class XCTickZone : public CObject +{ + // + // Public ... + public: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double high; + double low; + int ticks; + double percent; + + // + ulong volume; + double volumePercent; + + // + // Compare Two Zone With Each Other ... + virtual int Compare( + const CObject *node, + const int mode = 0 // + ) const + { + // + const XCTickZone *other = (XCTickZone *)node; + + // + return other.ticks - ticks; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = high > 0 && + low > 0 && + high > low && + ticks > 0 && + percent > 0; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // +}; + +// +class XCTicksZone : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCTicksZone() + { + Default(); + } + + // + // Deconstructor ... + void ~XCTicksZone() + { + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Number of Ticks Levels ... + * + * @return ( int ) + */ + int Levels() + { + return mLevels; + } + + /** + * Set Number of Ticks Levels ... + * + * @return ( int ) + */ + void Levels(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mLevels = value; + } + + /** + * Apply Default Config ... + */ + virtual void Default() + { + // + Levels(10); + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = endBar.period; + } + + // + // Calculate Start and End Time ... + datetime from = startBar.time; + datetime to = endBar.time; + ulong fromM = ((ulong)to * 1000); + ulong toM = ((ulong)from * 1000); + + // + // Symbol and Period ... + string symbol = startBar.symbol; + ENUM_TIMEFRAMES period = startBar.period; + + // + // Prepare Zones Array ... + mZones.Clear(); + + // + // Retrieve Ticks between Times ... + SpecificClean(mTicks); + int res = CopyTicksRange( + symbol, + mTicks, + COPY_TICKS_ALL, + fromM, + toM // + ); + + // + // Ticks Volumes ... + int ticksVolumeCount = CopyTickVolume( + symbol, + forPeriod, + from, + to, + mTickVolumes // + ); + if (IsValidSize(ticksVolumeCount)) + { + // + mVolumes = 0; + for (int i = 0; i < ticksVolumeCount; i++) + { + mVolumes += mTickVolumes[i]; + } + } + + // + // Retrieve Highs ... + SpecificClean(mHighs); + CopyHigh( + symbol, + period, + from, + to, + mHighs // + ); + + // + // Retrieve Lows ... + SpecificClean(mLows); + CopyLow( + symbol, + period, + from, + to, + mLows // + ); + + // + // Find Highest Value in Range ... + int highIDX = ArrayMaximum(mHighs); + mRangeHigh = mHighs[highIDX]; + + // + // Find Lowest Value in Range ... + int lowIDX = ArrayMinimum(mLows); + mRangeLow = mLows[lowIDX]; + + // + datetime mTimes[]; + CopyTime( + symbol, + period, + from, + to, + mTimes // + ); + mRangeHighTime = mTimes[highIDX]; + mRangeLowTime = mTimes[lowIDX]; + + // + double mRangeSize = mRangeHigh - mRangeLow; + + // + // Create Zones ... + for (int i = 0; i < Levels(); i++) + { + // + // Instance a New Zone ... + XCTickZone *iZone = new XCTickZone(); + + // + iZone.symbol = symbol; + iZone.period = period; + + // + // Calculate Each Zones High / Low based on Range ... + double iH = mRangeHigh - mRangeSize * i / Levels(); + double iL = mRangeHigh - mRangeSize * (i + 1) / Levels(); + + // + // Set Zone High Low Properties ... + iZone.low = iL; + iZone.high = iH; + + // + // Add Zone to Zone Array Objects ... + mZones.Add(iZone); + } + + // + // Calculate Each Zone Ticks ... + int ticksCount = ArraySize(mTicks); + for (int i = 0; i < ticksCount; i++) + { + // + // Retrieve Tick ... + MqlTick iTick = mTicks[i]; + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + // Rejrieve j indexed Zone Object ... + XCTickZone *jZone = mZones.At(j); + + // + bool isInRange = IsTickInZoneRange( + iTick, + jZone // + ); + if (isInRange) + { + // + jZone.ticks++; + break; + } + } + } + + // + // Calculating Zone Percents ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + double percent = CalculateZoneTickPercent(iZone); + iZone.percent = percent; + } + + // + // Sort Zones Based on Percents ... + mZones.Sort(); + + // + mUpper = mRangeHigh; + mLower = mRangeLow; + mType = X_POI_TICKS_ZONES; + mEndBar = endBar; + mStartBar = startBar; + From(endBar.time); + To(startBar.time); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Try to Find Out PERIOD_1M times in each zone ... + datetime to1M = (datetime)((int)endBar.time + PeriodSeconds(period) - 60); + int to1MIndex = iBarShift( + symbol, + forPeriod, + to1M // + ); + int from1MIndex = iBarShift( + symbol, + forPeriod, + from // + ); + for (int i = from1MIndex; i > to1MIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + forPeriod, + i // + ); + if (!isInited) + { + continue; + } + ulong iVolume = iTickVolume( + symbol, + forPeriod, + i // + ); + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + XCTickZone *jZone = mZones.At(j); + if (!jZone.IsValid()) + { + continue; + } + + // + // Check iBar is Inside jZone ... + bool isIBarInside = + iBar.GetUp() < jZone.high && + iBar.GetDown() > jZone.low; + // iBar.low < jZone.high || + // iBar.high > jZone.low; + if (isIBarInside) + { + jZone.volume += iVolume; + } + } + } + + // + // Calculate Volume Percent ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + if (mVolumes > 0) + { + iZone.volumePercent = (double)(iZone.volume * 100 / mVolumes); + } + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Zones Count ... + * + * @return ( int ) + */ + int Count() + { + return mZones.Total(); + } + + /** + * Retrieve Specified Sorted Zones ... + * + * @param index: Integer ... + * + * @return ( XCTickZone * ) + */ + XCTickZone *GetZone(int index) + { + // + if (!IsValidIndex(index)) + { + return NULL; + } + + // + return mZones.At(index); + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price // + ) + { + // + double result = 0; + + // + int count = Count(); + if (price <= 0 || + !IsValid() || + !IsValidSize(count) || + forDirection == X_DIRECTION_ALL || + forDirection == X_DIRECTION_NONE) + { + return result; + } + + // + bool isBullish = forDirection == X_DIRECTION_BULLISH; + + // + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + if (iZone.IsValid()) + { + // + result += !isBullish && + price > iZone.high + ? iZone.percent + : isBullish && + price < iZone.low + ? iZone.percent + : 0; + } + } + + // + return result; + } + + // + // Overrides ... + bool IsValid() override + { + // + bool result = false; + + // + result = + IsValidFrom() && + IsValidTwoBarZone() && + Levels() > 0 && + mZones.Total() == Levels() && + mRangeHigh > 0 && + mRangeLow > 0; + + // + return result; + } + + // + bool GetMaxTickZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.ticks < iZone.ticks + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + bool GetMinTickZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.ticks > iZone.ticks + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + bool GetMaxVolumeZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.volume < iZone.volume + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + bool GetMinVolumeZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.volume > iZone.volume + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + + // + MqlTick mTicks[]; + double mHighs[]; + double mLows[]; + ulong mVolumes; + ulong mTickVolumes[]; + double mRangeHigh; + datetime mRangeHighTime; + double mRangeLow; + datetime mRangeLowTime; + + // + int mLevels; // Number of Ticks Levels ... + + // + CArrayObj mZones; + + /** + * Check a Tick is in a Zone rage or not ... + * + * @param tick: MqlTick instance ... + * @param zone: XCTickZone instance ... + * + * @return ( bool ) + */ + bool IsTickInZoneRange( + MqlTick &tick, + XCTickZone *zone // + ) + { + // + bool result = false; + + // + result = + // + tick.bid >= zone.low && + tick.bid <= zone.high + // + ; + + // + return result; + } + + /** + * Calculate Zone Tick Percent ... + * + * @param zone: XCTickZone instance ... + * @param normalizationDigits: Integer ... + * + * @return ( double ) + */ + double CalculateZoneTickPercent( + XCTickZone *zone, + int normalizationDigits = 2 // + ) + { + // + double result = 0; + + // + if (normalizationDigits < 2 || normalizationDigits > 5) + { + normalizationDigits = 2; + } + + // + int ticksCount = ArraySize(mTicks); + if (ticksCount <= 0) + { + return result; + } + + // + result = (double)zone.ticks / ticksCount * 100; + result = NormalizeDouble(result, normalizationDigits); + + // + return result; + } + + // +}; + +// +// Trading Day ... +class XCDay : public XCFromToZone +{ + // + public: + // + + // + // Constructor ... + void XCDay() + { + } + + // + // Deconstructor ... + void ~XCDay() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @return ( bool ) + */ + bool Init() + { + // + bool result = false; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + protected: + // + + // + private: + // + + // +}; + +// +// Trading Session ... +class XCSession : public XCFromToZone +{ + // + public: + // + + // + // Constructor ... + void XCSession() + { + } + + // + // Deconstructor ... + void ~XCSession() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @return ( bool ) + */ + bool Init() + { + // + bool result = false; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + protected: + // + + // + private: + // + + // +}; + + +// + + + +template +bool ToBox( + T *&source[], + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + item // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +int GetOldest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetOldest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetYoungest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetYoungest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetLowest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetLowest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetHighest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetHighest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +bool IsSame( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSameAs(destBox); + + // + return result; +} + +template +bool 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 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 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 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; +} + +// +// +// + +// +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; +} + +/** + * 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; +} + +/** + * 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); + } +} + + +/** + * Check a Box is Used or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxUsed( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + bool isTouched = false; + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + isTouched = + isInited && + (isBullish + ? iBar.low > box.upper + : iBar.high < box.lower); + if (!isTouched) + { + continue; + } + + // + iBar.Clean(); + break; + } + + // + result = isTouched; + + // + return result; +} + +/** + * Validate Box ... + * + * @param box: XBoxZone instance ... + * @param barIndex: int, Current Bar Index ... + * @param forPeriod: Testing Period ... + * + * @return ( bool ) + */ +bool IsBoxValid( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int toIndex = iBarShift( + box.symbol, + forPeriod, + box.to // + ); + result = IsValidIndex(toIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < toIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.low > box.upper + : iBar.high < box.lower; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Check Box Breaked ... + * + * @param box: XBoxZone instance ... + * @param barIndex: int, Current Bar Index ... + * @param forPeriod: Testing Period ... + * + * @return ( bool ) + */ +bool IsBoxBreaked( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int toIndex = iBarShift( + box.symbol, + forPeriod, + box.to // + ); + result = IsValidIndex(toIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < toIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.high < box.lower + : iBar.low > box.upper; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Check a Box is Breaked or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxBreaked( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + bool isBreaked = false; + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + isBreaked = + isInited && + (isBullish + ? iBar.high <= box.lower + : iBar.low >= box.upper); + if (!isBreaked) + { + continue; + } + + // + iBar.Clean(); + break; + } + + // + result = isBreaked; + + // + return result; +} + +/** + * Check a BaxHas Valid Place for Specified Bar ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * #param box: XBoxZone instance reference, Specified Box ... + * + * @return ( bool ) + */ +bool IsBoxPlaceValidForBar( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + box.IsBullish() + ? bar.low > box.upper + : bar.high < box.upper; + + // + return result; +} + + +/** + * Check Source Box is Below Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxBelow( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.upper < dest.lower; + } + else + { + result = (source.upper < dest.lower || + source.upper >= dest.upper) && + source.lower < dest.lower; + } + + // + return result; +} + +/** + * Check Source Box is Above Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxAbove( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.lower > dest.upper; + } + else + { + result = (source.lower > dest.upper || + source.lower <= dest.upper) && + source.upper > dest.upper; + } + + // + return result; +} + +/** + * Check Source Box is Inside Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param forceSideOut: bool, force check Box has One Side Out ... + * @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ... + * + * @return ( bool ) + */ +bool IsBoxInside( + XBoxZone &source, + XBoxZone &dest, + bool forceSideOut = false, // + bool ignoreSideOut = true // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dest.dir); + + // + if (!forceSideOut) + { + // + if (ignoreSideOut) + { + // + result = source.lower >= dest.lower && + source.upper <= dest.upper; + } + else + { + result = source.lower >= dest.lower || + source.upper <= dest.upper; + } + } + else + { + // + bool hasSideIn = + isBullish + ? source.lower >= dest.lower + : source.upper <= dest.upper; + bool hasSideOut = + isBullish + ? source.upper >= dest.upper + : source.lower <= dest.lower; + result = + hasSideIn && + hasSideOut; + } + + // + return result; +} + +/** + * Detect source BoX is Inside Dest Box or Have a Side Out on it ... + * + * @param source: XBoxZone instance, source box which checks by dest ... + * @param dest: XBoxZone instance, dest Box which compares source with it ... + * + * @return ( bool ) + */ +bool IsBoxInsideOr( + XBoxZone &source, + XBoxZone &dest, + bool forceInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + bool isInside = + source.upper <= dest.upper && + source.upper >= dest.lower && + source.lower >= dest.lower && + source.lower <= dest.upper; + bool isUpperInside = + source.upper <= dest.upper && + source.upper >= dest.lower; + bool isLowerInside = + source.lower >= dest.lower && + source.lower <= dest.upper; + + // + result = + forceInside + ? isInside + : (isInside || + isLowerInside || + isUpperInside); + + // + return result; +} + +/** + * Check Value is Inside Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value <= box.upper && + value >= box.lower; + + // + return result; +} + +/** + * Check Bar is Inside Specified Box ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + bar.close <= box.upper && + bar.close >= box.lower; + + // + return result; +} + +/** + * Check Value is Above Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsAboveBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value > box.upper; + + // + return result; +} + +/** + * Check Value is Below Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsBelowBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value < box.lower; + + // + return result; +} + +/** + * 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; +} diff --git a/BKPS/14040626/Documents/BKP/x-saherelm.x-cobject.class.mq5 b/BKPS/14040626/Documents/BKP/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..91cc37c --- /dev/null +++ b/BKPS/14040626/Documents/BKP/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,3478 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XChartObjects +// Description: provides all require Chart Objects ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +#include +#include +#include +#include +#include +#include + +// +// Definitions ... + +enum ENUM_XCHARTOBJECTS +{ + // + // Global ... + X_ZONE_OBJ = 7860, + X_BOX_OBJ = 7861, + X_BAR_ARROW_OBJ = 7862, + // + X_SIGNAL_OBJ = 8860, + X_TREND_OBJ = 8861, + X_XPVPIVOT_OBJ = 8862, + X_OHCL_OBJ = 8863, + X_RR_OBJ = 8864, + // + // Structured ... + X_TRADE_DAY_OBJ = 9860, + X_MARKET_SESSION_OBJ = 9861, + X_SWING_HIGH_OBJ = 9862, + X_SWING_LOW_OBJ = 9863, + X_BULLISH_MOMENTUM_BAR_OBJ = 9864, + X_BEARISH_MOMENTUM_BAR_OBJ = 9865, + X_BULLISH_REJECTION_BAR_OBJ = 9866, + X_BEARISH_REJECTION_BAR_OBJ = 9867, + X_SUPPORT_ZONE_OBJ = 9868, + X_RESISTANCE_ZONE_OBJ = 9869, + X_SUPPLY_ZONE_OBJ = 9870, + X_DEMAND_ZONE_OBJ = 9871, + X_BULLISH_ORDERBLOCK_OBJ = 9872, + X_BEARISH_ORDERBLOCK_OBJ = 9873, + X_BULLISH_FVG_OBJ = 9874, + X_BEARISH_FVG_OBJ = 9875, + X_TICK_ZONE_OBJ = 9876, + X_TICKS_ZONE_OBJ = 9877, + X_CONSOLIDATION_ZONE_OBJ = 9878, +}; + +enum ENUM_X_CHART_IDS +{ + X_TO, + X_FROM, + X_UPPER, + X_LOWER, + X_ENTRY, + X_TARGET, + X_SL, + X_TP, + X_BAR_H_SHW, + X_BAR_BDY, + X_BAR_L_SHW, +}; + +string ToString(ENUM_X_CHART_IDS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_TO: + result = "TO"; + break; + + // + case X_FROM: + result = "FROM"; + break; + + // + case X_UPPER: + result = "UPPER"; + break; + + // + case X_LOWER: + result = "LOWER"; + break; + + // + case X_ENTRY: + result = "ENTRY"; + break; + + // + case X_TARGET: + result = "TARGET"; + break; + + // + case X_SL: + result = "SL"; + break; + + // + case X_TP: + result = "TP"; + break; + + // + case X_BAR_H_SHW: + result = "HSHW"; + break; + + // + case X_BAR_BDY: + result = "BODY"; + break; + + // + case X_BAR_L_SHW: + result = "LSHW"; + break; + + // + } + + // + return result; +} + +// +// Extensions ... + +/** + * Converts a XBoxZone struct to XSignal instance ... + * + * @param box: XBoxZone instance reference, provide source info ... + * @param signal: XSignal instance reference, holds prepared converted signal ... + * + * @return ( bool ) + */ +bool ToSignal( + XBoxZone &box, + XSignal &signal, + double &rewardRatios[], + double additionalSL = 0 // +) +{ + // + bool result = false; + + // + signal.Clean(); + + // + result = box.IsValid() && + HasChild(rewardRatios); + if (!result) + { + return result; + } + + // + XOHCL entryBar; + int entryIDX = box.ToIndex(); + if (entryIDX > 0) + { + entryIDX--; + } + result = entryBar.Init( + box.symbol, + box.period, + entryIDX // + ); + if (!result) + { + // + entryBar.Clean(); + + // + return result; + } + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + ENUM_POSITION_TYPE iType = + isBullish + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES iXType = + isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + double points = GetPoints(box.symbol); + + // + double entry = + isBullish + ? box.upper + : box.lower; + entry = entryBar.open; + + // + double sl = + isBullish + ? box.lower + : box.upper; + if (additionalSL > 0) + { + // + sl = + isBullish + ? sl - additionalSL + : sl + additionalSL; + } + + // + double risk = MathAbs(entry - sl); + + // + double tp = 0; + + // + // Calculate Target ... + XTarget targets[]; + + // + double tmp[]; + int idx = -1; + XTarget iTarget; + bool has = false; + double iRatio = 0; + double iReward = 0; + double iRewardPrice = 0; + Copy( + rewardRatios, + tmp // + ); + while (HasChild(tmp)) + { + // + idx = -1; + iRatio = GetMaxWidthIndex( + tmp, + idx // + ); + + // + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + has = iRatio > 0; + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + bool canSetTP = tp <= 0; + + // + iReward = iRatio * risk; + + // + iRewardPrice = + isBullish + ? entry + iReward + : entry - iReward; + if (canSetTP) + { + tp = iRewardPrice; + } + else + { + // + iTarget.target = iRewardPrice; + AddRef( + iTarget, + targets // + ); + + // + iTarget.Clean(); + } + } + Clean(tmp); + + // + // Filling Signal ... + signal.tp = tp; + signal.sl = sl; + signal.type = iType; + signal.comment = ""; + signal.entry = entry; + signal.time = box.to; + signal.volume = 0.01; + signal.provider = box.type; + signal.symbol = box.symbol; + signal.period = box.period; + signal.mode = X_ORDER_MODE_MARKET; + + // + if (HasChild(targets)) + { + // + Copy( + targets, + signal.targets // + ); + } + + // + result = signal.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + signal.Clean(); + } + + // + Clean(tmp); + Clean(targets); + iTarget.Clean(); + entryBar.Clean(); + + // + return result; +} + +// +// Implementation ... + +// +// Global Chart Objects ... + +// +// Bas Chart Object ... +class XCBaseObject : public CChartObject +{ + // + public: + // + + // + // Getter(s) / Setter(s) ... + + /** + * Get Object Specified Name ... + * + * @return ( string ) + */ + string ObjName() + { + return mObjName; + } + + /** + * Set Object Specified Name ... + * + * @param value: String ... + */ + void ObjName(string value) + { + mObjName = value; + } + + // + private: + // + + // + // Props ... + string mObjName; // Object Specified Name ... + + // +}; + +class XCBarArrowObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * + * @return ( bool ) + */ + bool CreateByBar( + long chart_id, + string name, + int window, + int arrow, + XOHCL &bar, + ENUM_X_PRICE priceType, + double threshold = 5 // + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + IsValid(name) + // + ; + if (!result) + { + return result; + } + + // + datetime time = bar.time; + double price = bar.GetPrice(priceType); + + // + if (threshold > 0) + { + // + double thresholdPrice = threshold * GetPoints(bar.symbol); + if (priceType == X_PRICE_HIGH) + { + price += thresholdPrice; + } + else if (priceType == X_PRICE_LOW) + { + price -= thresholdPrice; + } + } + + // + result = mArrow.Create( + chart_id, + name, + window, + time, + price, + (char)arrow // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + // + // Setter(s) ... + + /** + * Set Arrow Anchor ... + * + * @param value: ENUM_ARROW_ANCHOR member ... + */ + void ArrowAnchor(ENUM_ARROW_ANCHOR value) + { + mArrow.Anchor(value); + } + + /** + * Set Arrow Color ... + * + * @param value: Color ... + */ + void ArrowColor(color value) + { + mArrow.Color(value); + } + + /** + * Set Arrow Width ... + * + * @param value: Integer ... + */ + void ArrowWidth(int value) + { + mArrow.Width(value); + } + + // + private: + // + CChartObjectArrow mArrow; + + // +}; + +// +// Swing ... +class XCSwingObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateBySwing( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + swing.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = swing.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = swing.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = swing.IsSwingHigh() + ? X_PRICE_HIGH + : X_PRICE_LOW; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Swing High ... +class XCSwingHighObject : public XCSwingObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = swing.IsValid() && + swing.IsSwingHigh(); + if (!result) + { + return result; + } + + // + result = CreateBySwing( + chart_id, + window, + arrow, + swing, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SWING_HIGH_OBJ; + } + + // +}; + +// +// Swing Low ... +class XCSwingLowObject : public XCSwingObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = swing.IsValid() && + swing.IsSwingLow(); + if (!result) + { + return result; + } + + // + result = CreateBySwing( + chart_id, + window, + arrow, + swing, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SWING_LOW_OBJ; + } + + // +}; + +// +// Momentum ... +class XCMomentumBarObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByMomentum( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + momentumBar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = momentumBar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = momentumBar.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = momentumBar.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Bullish Momentum Bar ... +class XCBullishMomentumBarObject : public XCMomentumBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = momentumBar.IsValid() && + momentumBar.IsBullish(); + if (!result) + { + return result; + } + + // + result = CreateByMomentum( + chart_id, + window, + arrow, + momentumBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_MOMENTUM_BAR_OBJ; + } + + // +}; + +// +// Bearish Momentum Bar ... +class XCBearishMomentumBarObject : public XCMomentumBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = momentumBar.IsValid() && + momentumBar.IsBearish(); + if (!result) + { + return result; + } + + // + result = CreateByMomentum( + chart_id, + window, + arrow, + momentumBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_MOMENTUM_BAR_OBJ; + } + + // +}; + +// +// Rejection ... +class XCRejectionBarObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByRejection( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + rejectionBar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = rejectionBar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = rejectionBar.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = rejectionBar.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Bullish Rejection Bar ... +class XCBullishRejectionBarObject : public XCRejectionBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rejectionBar.IsValid() && + rejectionBar.IsBullish(); + if (!result) + { + return result; + } + + // + result = CreateByRejection( + chart_id, + window, + arrow, + rejectionBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_REJECTION_BAR_OBJ; + } + + // +}; + +// +// Bearish Rejection Bar ... +class XCBearishRejectionBarObject : public XCRejectionBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rejectionBar.IsValid() && + rejectionBar.IsBearish(); + if (!result) + { + return result; + } + + // + result = CreateByRejection( + chart_id, + window, + arrow, + rejectionBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_REJECTION_BAR_OBJ; + } + + // +}; + +// +// XCZoneObject ... +class XCZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object Identifier on Chart ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByZone( + long chart_id, + string name, + int window, + XCZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + bool isValidFrom = zone.IsValidFrom(); + bool isValidBoundary = zone.IsValidBoundary(); + + // + result = + // + IsValid(name) && + isValidFrom && + isValidBoundary + // + ; + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + datetime from = zone.From(); + datetime to = NormalizeTime(zone.To()); + + // + double upper = zone.Upper(); + double lower = zone.Lower(); + + // + result = mRect.Create( + chart_id, + name, + window, + from, + upper, + to, + lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_ZONE_OBJ; + } + + // + // Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + // + private: + // + CChartObjectRectangle mRect; + + // +}; + +// +// Support Zone ... +class XCSupportZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupportZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupportZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPORT_ZONE_OBJ; + } +}; + +// +// Resistance Zone ... +class XCResistanceZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCResistanceZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCResistanceZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RESISTANCE_ZONE_OBJ; + } +}; + +// +// Supply Zone ... +class XCSupplyZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupplyZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupplyZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPLY_ZONE_OBJ; + } +}; + +// +// Demand Zone ... +class XCDemandZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCDemandZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCDemandZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_DEMAND_ZONE_OBJ; + } +}; + +// +// Bullish Order Block ... +class XCBullishOrderBlockObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCOrderBlock &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_ORDERBLOCK_OBJ; + } +}; + +// +// Bearish Order Block ... +class XCBearishOrderBlockObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCOrderBlock &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_ORDERBLOCK_OBJ; + } +}; + +// +// Bullish Fair Value Gaps ... +class XCBullishFairValueGapObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCFVG &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_FVG_OBJ; + } +}; + +class XCConsolidationZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XConsolidationZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XConsolidationZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + result = mRect.Create( + chart_id, + name, + window, + zone.from, + zone.upper, + zone.to, + zone.lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_CONSOLIDATION_ZONE_OBJ; + } + + // + // Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + // + private: + // + CChartObjectRectangle mRect; + + // +}; + +// +// Bearish Fair Value Gaps ... +class XCBearishFairValueGapObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCFVG &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_FVG_OBJ; + } +}; + +// +// Signal ... +class XCSignalObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + void XCSignalObject() + { + } + + // + // Deconstructor ... + void ~XCSignalObject() + { + } + + /** + * Create a Signal Object on Chart ... + * + * @param chart_id: Long ... + * @param name: String ... + * @param window: Integer ... + * @param signal: XSignal instance ... + * @param length: int, Specified Length of Signal ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + const int window, + XSignal &signal, + int length = 3, + string prefix = NULL // + ) + { + // + bool result = false; + + // + length = NormalizeInt(length, 3); + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string name = signal.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + int delay = (PeriodSeconds(signal.period) * length); + datetime time1 = (datetime)((int)signal.time - delay); + datetime time2 = (datetime)((int)signal.time + delay); + + // + // TP ... + string tpName = ToString(X_TP) + "_" + nameMD5; + result = mTPTrend.Create( + chart_id, + tpName, + window, + time1, + signal.tp, + time2, + signal.tp // + ); + if (!result) + { + return result; + } + + // + // SL ... + string slName = ToString(X_SL) + "_" + nameMD5; + result = mSLTrend.Create( + chart_id, + slName, + window, + time1, + signal.sl, + time2, + signal.sl // + ); + if (!result) + { + // + mTPTrend.Delete(); + return result; + } + + // + // TARGET ... + bool hasTargets = HasChild(signal.targets); + if (hasTargets) + { + // + int targetsCount = ArraySize(signal.targets); + for (int i = 0; i < targetsCount; i++) + { + // + string targetName = ToString(X_TARGET) + "_" + ToString(i) + "_" + nameMD5; + CChartObjectTrend *mTargetTrend; + mTargetTrend = new CChartObjectTrend(); + result = mTargetTrend.Create( + chart_id, + targetName, + window, + time1, + signal.targets[i].target, + time2, + signal.targets[i].target // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + break; + } + + // + mTargetTrends.Add(mTargetTrend); + } + } + + // + // ENTRY ... + string entrName = ToString(X_ENTRY) + "_" + nameMD5; + result = mEntryTrend.Create( + chart_id, + entrName, + window, + time1, + signal.entry, + time2, + signal.entry // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + mTargetTrends.Clear(); + return result; + } + + // + // Set Object Name ... + ObjName(name); + + // + return result; + } + + // + // Setter(s) ... + + // + // TP ... + + /** + * Set TP Width ... + * + * @param value: Integer ... + */ + void TPWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mTPTrend.Width(value); + } + + /** + * Set TP Color ... + * + * @param value: Color ... + */ + void TPColor(color value) + { + mTPTrend.Color(value); + } + + /** + * Set TP Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TPStyle(ENUM_LINE_STYLE value) + { + mTPTrend.Style(value); + } + + // + // SL ... + + /** + * Set SL Width ... + * + * @param value: Integer ... + */ + void SLWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSLTrend.Width(value); + } + + /** + * Set SL Color ... + * + * @param value: Color ... + */ + void SLColor(color value) + { + mSLTrend.Color(value); + } + + /** + * Set SL Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void SLStyle(ENUM_LINE_STYLE value) + { + mSLTrend.Style(value); + } + + // + // TARGET ... + + /** + * Set Target Width ... + * + * @param value: Integer ... + */ + void TargetWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Width(value); + } + } + + /** + * Set Target Color ... + * + * @param value: Color ... + */ + void TargetColor(color value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Color(value); + } + } + + /** + * Set Target Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TargetStyle(ENUM_LINE_STYLE value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Style(value); + } + } + + // + // ENTRY ... + + /** + * Set Entry Width ... + * + * @param value: Integer ... + */ + void EntryWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mEntryTrend.Width(value); + } + + /** + * Set Entry Color ... + * + * @param value: Color ... + */ + void EntryColor(color value) + { + mEntryTrend.Color(value); + } + + /** + * Set Entry Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void EntryStyle(ENUM_LINE_STYLE value) + { + mEntryTrend.Style(value); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SIGNAL_OBJ; + } + + // + private: + // + + // + CChartObjectTrend mTPTrend; + CChartObjectTrend mSLTrend; + CChartObjectTrend mEntryTrend; + CArrayObj mTargetTrends; +}; + +// +// XRR Object ... +class XCRRObject : public XCSignalObject +{ + // + // Public ... + public: + // + // Constructor ... + bool CreateBoxRR( + long chart_id, + const int window, + XBoxZone &box, + double &rewardRatios[], + int length = 3, + string prefix = NULL // + ) + { + // + bool result = false; + + // + length = NormalizeInt(length, 3); + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + XSignal signal; + result = ToSignal( + box, + signal, + rewardRatios // + ); + if (!result) + { + // + signal.Clean(); + + // + return result; + } + + // + result = Create( + chart_id, + window, + signal, + length, + prefix // + ); + + // + signal.Clean(); + + // + return result; + } +}; + +class XCOHCLObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XOHCL &bar, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + IsValid(to); + if (!result) + { + return result; + } + + // + string name = bar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + // High Shadow ... + string hShadowName = ToString(X_BAR_H_SHW) + "_" + nameMD5; + + // + result = mHighShadowRect.Create( + chart_id, + hShadowName, + window, + bar.time, + bar.high, + to, + bar.GetUp() // + ); + if (!result) + { + return result; + } + + // + // Body ... + string bodyName = ToString(X_BAR_BDY) + "_" + nameMD5; + + // + result = mBodyRect.Create( + chart_id, + bodyName, + window, + bar.time, + bar.GetUp(), + to, + bar.GetDown() // + ); + if (!result) + { + // + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + // Low Shadow ... + string lShadowName = ToString(X_BAR_L_SHW) + "_" + nameMD5; + + // + result = mLowShadowRect.Create( + chart_id, + lShadowName, + window, + bar.time, + bar.GetDown(), + to, + bar.low // + ); + if (!result) + { + // + mBodyRect.Delete(); + mBodyRect.Detach(); + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set High Shadow Width ... + * + * @param value: Integer ... + */ + void HighShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mHighShadowRect.Width(value); + } + + /** + * Set High Shadow Color ... + * + * @param value: Color ... + */ + void HighShadowColor(color value) + { + mHighShadowRect.Color(value); + } + + /** + * Set High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void HighShadowStyle(ENUM_LINE_STYLE value) + { + mHighShadowRect.Style(value); + } + + /** + * Set High Shadow Fill ... + * + * @param value: Boolean ... + */ + void HighShadowFill(bool value) + { + mHighShadowRect.Fill(value); + } + + /** + * Set Body Width ... + * + * @param value: Integer ... + */ + void BodyWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBodyRect.Width(value); + } + + /** + * Set Body Color ... + * + * @param value: Color ... + */ + void BodyColor(color value) + { + mBodyRect.Color(value); + } + + /** + * Set Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BodyStyle(ENUM_LINE_STYLE value) + { + mBodyRect.Style(value); + } + + /** + * Set Body Fill ... + * + * @param value: Boolean ... + */ + void BodyFill(bool value) + { + mBodyRect.Fill(value); + } + + /** + * Set Low Shadow Width ... + * + * @param value: Integer ... + */ + void LowShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mLowShadowRect.Width(value); + } + + /** + * Set Low Shadow Color ... + * + * @param value: Color ... + */ + void LowShadowColor(color value) + { + mLowShadowRect.Color(value); + } + + /** + * Set Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void LowShadowStyle(ENUM_LINE_STYLE value) + { + mLowShadowRect.Style(value); + } + + /** + * Set Low Shadow Fill ... + * + * @param value: Boolean ... + */ + void LowShadowFill(bool value) + { + mLowShadowRect.Fill(value); + } + + void BarSpes( + int width = 1, + color clr = clrNONE, + ENUM_LINE_STYLE style = STYLE_SOLID, + bool fill = false // + ) + { + // + BodyWidth(width); + LowShadowWidth(width); + HighShadowWidth(width); + + // + BodyColor(clr); + LowShadowColor(clr); + HighShadowColor(clr); + + // + BodyStyle(style); + LowShadowStyle(style); + HighShadowStyle(style); + + // + BodyFill(fill); + LowShadowFill(fill); + HighShadowFill(fill); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_OHCL_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mHighShadowRect; + CChartObjectRectangle mBodyRect; + CChartObjectRectangle mLowShadowRect; +}; + +class XCBoxObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + double upper, + double lower, + datetime from, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + upper > 0 && + lower > 0 && + to > from && + IsValid(to) && + IsValid(name) && + IsValid(from) && + upper > lower; + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mRect.Create( + chart_id, + name, + window, + from, + upper, + to, + lower // + ); + if (!result) + { + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void BoxWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void BoxColor(color value) + { + mRect.Color(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BoxStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Fill ... + * + * @param value: Boolean ... + */ + void BoxFill(bool value) + { + mRect.Fill(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BOX_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mRect; +}; + +// +// Zone Ticks ... + +// +// Specify How to Draws Specified Levels ... +struct XTickZoneLevelSpecs +{ + // + double percent; // Max Allowed Percent of Tick Zone ... + + // + // Label Info ... + color labelColor; + string labelFont; + int labelFontSize; + double labelAngel; + + // + // Zone Info ... + bool zoneFill; + int zoneWidth; + color zoneColor; + ENUM_LINE_STYLE zoneStyle; + + // + // Constructor ... + XTickZoneLevelSpecs() + { + Default(); + } + + // + // Tools ... + + /** + * Initialize Drawing Specs ... + * + * @param _percent: Double, Max Allowed Percent ... + * @param _labelColor: Color, Specified Label Color ... + * @param _zoneColoe: Color, Specified Zone Color ... + * @param _zoneFill: Boolean, Specified Fill Zone or not ... + * @param _zoneStyle: ENUM_LINE_STYLE member, Specified Zone Style ... + * @param _labelFontSize: Integer, Specified Label Font Size ... + * @param _labelFont: String, Specified Label Font Name ... + * @param _labelAngel: Double, Specified Label Angel ... + * + * @return ( bool ) + */ + bool Init( + double _percent, + color _labelColor = clrWhite, + color _zoneColor = clrWhite, + bool _zoneFill = false, + ENUM_LINE_STYLE _zoneStyle = STYLE_DOT, + int _zoneWidth = 1, + int _labelFontSize = 12, + string _labelFont = "Arial", + double _labelAngel = 0 // + ) + { + // + bool result = false; + + // + Default(); + + // + result = _percent > 0; + if (!result) + { + return result; + } + + // + percent = _percent; + labelColor = _labelColor; + zoneColor = _zoneColor; + zoneFill = _zoneFill; + zoneStyle = _zoneStyle; + + // + if (_zoneWidth > 0) + { + zoneWidth = _zoneWidth; + } + + // + if (_labelFontSize > 0) + { + labelFontSize = _labelFontSize; + } + + // + if (IsSpecifiedValid(_labelFont)) + { + labelFont = _labelFont; + } + + // + if (_labelAngel >= 0) + { + labelAngel = _labelAngel; + } + + // + result = IsValid(); + + // + return result; + } + + /** + * Set Default Properties ... + */ + void Default() + { + // + percent = 0; + + // + // Label ... + labelAngel = 0; + labelFontSize = 13; + labelFont = "Arial"; + labelColor = clrWhite; + + // + // Zone ... + zoneWidth = 1; + zoneFill = false; + zoneColor = clrWhite; + zoneStyle = STYLE_DOT; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + percent > 0 && + // + // Zone ... + zoneWidth > 0 && + // + // Label ... + labelFontSize > 0 && + IsSpecifiedValid(labelFont) + // + ; + + // + return result; + } + + // +}; + +class XCTickZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param name: String, Specify Chart Object Identifier ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param zone: XCTickZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + datetime from, + datetime to, + XCTickZone *zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + IsValid(name) && + zone.IsValid() && + IsValid(to) && + IsValid(from); + if (!result) + { + return result; + } + + // + double points = GetPoints(zone.symbol); + if (points <= 0) + { + points = 1; + } + double distance = 1 * points; + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + string rectName = "TKZ_" + name; + result = mRect.Create( + chart_id, + rectName, + window, + from, + zone.high, + to, + zone.low // + ); + if (!result) + { + return result; + } + + // + int fromToDiff = ((int)to - (int)from); + datetime labelsDate = (datetime)((int)to - (fromToDiff / 5)); + + // + string lblName = "LBLT_" + name; + result = mTLabel.Create( + chart_id, + lblName, + window, + labelsDate, + zone.high - distance // + ); + if (!result) + { + return result; + } + + // + mTLabel.Description("T: " + ToString(zone.percent) + "%"); + + // + string lblVName = "LBLV_" + name; + result = mVLabel.Create( + chart_id, + lblVName, + window, + labelsDate, + zone.low + (2.5 * distance) // + ); + if (!result) + { + return result; + } + + // + mVLabel.Description("V: " + ToString(zone.volumePercent) + "%"); + + // + ObjName(name); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICK_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + /** + * Set Label Color ... + * + * @param value: Color ... + */ + void LabelColor(color value) + { + // + mTLabel.Color(value); + mVLabel.Color(value); + } + + /** + * Set Label Size ... + * + * @param value: Integer ... + */ + void LabelSize(int value) + { + // + mTLabel.FontSize(value); + mVLabel.FontSize(value); + } + + /** + * Set Label Font ... + * + * @param value: String ... + */ + void LabelFont(string value) + { + // + mTLabel.Font(value); + mVLabel.Font(value); + } + + /** + * Set Label Angle ... + * + * @param value: double ... + */ + void LabelAngle(double value) + { + // + mTLabel.Angle(value); + mVLabel.Angle(value); + } + + // + private: + // + // Props ... + CChartObjectRectangle mRect; + CChartObjectLabel mTLabel; + CChartObjectLabel mVLabel; + + // +}; +class XCTicksZoneObject : public XCBaseObject +{ + // + public: + // + + // + void ~XCTicksZoneObject() + { + mZones.Clear(); + } + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCTicksZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCTicksZone &zone, + XTickZoneLevelSpecs &specs[], + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + int levels = zone.Levels(); + result = levels > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < levels; i++) + { + // + XCTickZone *iZone = zone.GetZone(i); + XCTickZoneObject *iObj; + iObj = new XCTickZoneObject(); + bool isCreated = iObj.Create( + chart_id, + window, + ToString(i) + "_" + name, + zone.From(), + zone.To(), + iZone, + prefix // + ); + if (!isCreated) + { + break; + } + + // + XTickZoneLevelSpecs iSpec; + bool hasSpecs = FindSpecs( + iZone, + iSpec, + specs // + ); + if (hasSpecs) + { + // + // Label ... + iObj.LabelFont(iSpec.labelFont); + iObj.LabelAngle(iSpec.labelAngel); + iObj.LabelColor(iSpec.labelColor); + iObj.LabelSize(iSpec.labelFontSize); + + // + // Zone ... + iObj.ZoneFill(iSpec.zoneFill); + iObj.ZoneColor(iSpec.zoneColor); + iObj.ZoneWidth(iSpec.zoneWidth); + iObj.ZoneStyle(iSpec.zoneStyle); + } + + // + mZones.Add(iObj); + } + + // + if (result) + { + ObjName(name); + } + else + { + mZones.Clear(); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICKS_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + // + // Actions ... + + /** + * Destroy Object ... + */ + void Destroy() + { + mZones.Clear(); + } + + /** + * Find Specified TickZone Drawing Specs ... + * + * @param zone: XCTickZone instance, reference to Search For it ... + * @param spec: XTickZoneLevelSpecs instance, reference to Result ... + * @param specs: XTickZoneLevelSpecs instance Collection for Search ... + * + * @return ( bool ) + */ + bool FindSpecs( + XCTickZone *zone, + XTickZoneLevelSpecs &spec, + XTickZoneLevelSpecs &specs[] // + ) + { + // + bool result = false; + + // + int count = ArraySize(specs); + result = + zone.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XTickZoneLevelSpecs iSpecs = specs[i]; + + // + bool isSpecValidForZone = + !spec.IsValid() + ? zone.percent <= iSpecs.percent + : zone.percent <= iSpecs.percent && + spec.percent > iSpecs.percent; + if (isSpecValidForZone) + { + spec = iSpecs; + } + } + + // + result = spec.IsValid(); + + // + return result; + } + + // + private: + // + // Props ... + CArrayObj mZones; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..51e7c7c --- /dev/null +++ b/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,4384 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + +// +// Extensions ... + +void AddObjects( + CArrayObj *&source, + CArrayObj &dest // +) +{ + // + bool has = source != NULL && + source.Total() > 0; + if (!has) + { + return; + } + + // + for (int i = 0; i < source.Total(); i++) + { + dest.Add(source.At(i)); + } +} + +// +// Implementations ... +class XCPOIDrawer : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCPOIDrawer() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDrawer() + { + // + Clean(mTicksZoneSpecs); + } + + // + // Setter Getter (s) ... + + /** + * Get Prefix ... + * + * @return ( string ) + */ + string Prefix() + { + return mPrefix; + } + + /** + * Set Prifx ... + * + * @param value: String ... + */ + void Prefix(string value) + { + mPrefix = value; + } + + /** + * Get Chart ID ... + * + * @return ( long ) + */ + long ChartIdentification() + { + return mChartIdentification; + } + + /** + * Set Chart ID ... + * + * @param value: Long ... + */ + void ChartIdentification(long value) + { + // + if (value < 0) + { + value = 0; + } + + // + mChartIdentification = value; + } + + /** + * Get SubWindow Id ... + * + * @return ( int ) + */ + int SubWindowIdentification() + { + return mSubWindowIdentification; + } + + /** + * Set SubWindow Id ... + * + * @param value: Integer ... + */ + void SubWindowIdentification(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSubWindowIdentification = value; + } + + // + // XOHCL ... + + /** + * Get Bar Width ... + * + * @return ( int ) + */ + int BarWidth() + { + return mBarWidth; + } + + /** + * Set Bar Width ... + * + * @param value: Integer ... + */ + void BarWidth(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mBarWidth = value; + } + + /** + * Get Bar Bullish Color ... + * + * @return ( color ) + */ + color BarBullishColor() + { + return mBarBullishColor; + } + + /** + * Set Bar Bullish Color ... + * + * @param value: Color ... + */ + void BarBullishColor(color value) + { + mBarBullishColor = value; + } + + /** + * Get Bar Bearish Color ... + * + * @return ( color ) + */ + color BarBearishColor() + { + return mBarBearishColor; + } + + /** + * Set Bar Bearish Color ... + * + * @param value: Color ... + */ + void BarBearishColor(color value) + { + mBarBearishColor = value; + } + + /** + * Get Fill Bar High Shadow State ... + * + * @return ( bool ) + */ + bool BarFillHighShadow() + { + return mBarFillHighShadow; + } + + /** + * Set Fill Bar High Shadow State ... + * + * @param value: Boolean ... + */ + void BarFillHighShadow(bool value) + { + mBarFillHighShadow = value; + } + + /** + * Get Bar High Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarHighShadowStyle() + { + return mBarHighShadowStyle; + } + + /** + * Set Bar High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarHighShadowStyle(ENUM_LINE_STYLE value) + { + mBarHighShadowStyle = value; + } + + /** + * Get Fill Bar Body State ... + * + * @return ( bool ) + */ + bool BarFillBody() + { + return mBarFillBody; + } + + /** + * Set Fill Bar Body State ... + * + * @param value: Boolean ... + */ + void BarFillBody(bool value) + { + mBarFillBody = value; + } + + /** + * Get Bar Body Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarBodyStyle() + { + return mBarBodyStyle; + } + + /** + * Set Bar Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarBodyStyle(ENUM_LINE_STYLE value) + { + mBarBodyStyle = value; + } + + /** + * Get Fill Bar Low Show State ... + * + * @return ( bool ) + */ + bool BarFillLowShadow() + { + return mBarFillLowShadow; + } + + /** + * Set Fill Bar Low Show State ... + * + * @param value: Boolean ... + */ + void BarFillLowShadow(bool value) + { + mBarFillLowShadow = value; + } + + /** + * Get Bar Low Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarLowShadowStyle() + { + return mBarLowShadowStyle; + } + + /** + * Set Bar Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarLowShadowStyle(ENUM_LINE_STYLE value) + { + mBarLowShadowStyle = value; + } + + // + // Swing Low ... + + /** + * Get Swing Low Width ... + * + * @return ( int ) + */ + int SwingLowWidth() + { + return mSwingLowWidth; + } + + /** + * Set Swing Low Width ... + * + * @param value: Integer ... + */ + void SwingLowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingLowWidth = value; + } + + /** + * Get Swing Low Arrow Code ... + * + * @return ( int ) + */ + int SwingLowArrow() + { + return mSwingLowArrow; + } + + /** + * Set Swing Low Arrow Code ... + * + * @param value: Integer ... + */ + void SwingLowArrow(int value) + { + // + mSwingLowArrow = value; + } + + /** + * Get Swing Low Color ... + * + * @return ( color ) + */ + color SwingLowColor() + { + return mSwingLowColor; + } + + /** + * Set Swing Low Color ... + * + * @param value: Color ... + */ + void SwingLowColor(color value) + { + mSwingLowColor = value; + } + + // + // Swing High ... + + /** + * Get Swing High Width ... + * + * @return ( int ) + */ + int SwingHighWidth() + { + return mSwingHighWidth; + } + + /** + * Set Swing High Width ... + * + * @param value: Integer ... + */ + void SwingHighWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingHighWidth = value; + } + + /** + * Get Swing High Arrow Code ... + * + * @return ( int ) + */ + int SwingHighArrow() + { + return mSwingHighArrow; + } + + /** + * Set Swing High Arrow Code ... + * + * @param value: Integer ... + */ + void SwingHighArrow(int value) + { + // + mSwingHighArrow = value; + } + + /** + * Get Swing High Color ... + * + * @return ( color ) + */ + color SwingHighColor() + { + return mSwingHighColor; + } + + /** + * Set Swing High Color ... + * + * @param value: Color ... + */ + void SwingHighColor(color value) + { + mSwingHighColor = value; + } + + // + // Bullish Momentum Bar ... + + /** + * Get Bullish Momentum Bar Width ... + * + * @return ( int ) + */ + int BullishMomentumBarWidth() + { + return mBullishMomentumBarWidth; + } + + /** + * Set Bullish Momentum Bar Width ... + * + * @param value: Integer ... + */ + void BullishMomentumBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishMomentumBarWidth = value; + } + + /** + * Get Bullish Momentum Bar Arrow Code ... + * + * @return ( int ) + */ + int BullishMomentumBarArrow() + { + return mBullishMomentumBarArrow; + } + + /** + * Set Bullish Momentum Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BullishMomentumBarArrow(int value) + { + // + mBullishMomentumBarArrow = value; + } + + /** + * Get Bullish Momentum Bar Color ... + * + * @return ( color ) + */ + color BullishMomentumBarColor() + { + return mBullishMomentumBarColor; + } + + /** + * Set Bullish Momentum Bar Color ... + * + * @param value: Color ... + */ + void BullishMomentumBarColor(color value) + { + mBullishMomentumBarColor = value; + } + + // + // Bearish Momentum Bar ... + + /** + * Get Bearish Momentum Bar Width ... + * + * @return ( int ) + */ + int BearishMomentumBarWidth() + { + return mBearishMomentumBarWidth; + } + + /** + * Set Bearish Momentum Bar Width ... + * + * @param value: Integer ... + */ + void BearishMomentumBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishMomentumBarWidth = value; + } + + /** + * Get Bearish Momentum Bar Arrow Code ... + * + * @return ( int ) + */ + int BearishMomentumBarArrow() + { + return mBearishMomentumBarArrow; + } + + /** + * Set Bearish Momentum Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BearishMomentumBarArrow(int value) + { + // + mBearishMomentumBarArrow = value; + } + + /** + * Get Bearish Momentum Bar Color ... + * + * @return ( color ) + */ + color BearishMomentumBarColor() + { + return mBearishMomentumBarColor; + } + + /** + * Set Bearish Momentum Bar Color ... + * + * @param value: Color ... + */ + void BearishMomentumBarColor(color value) + { + mBearishMomentumBarColor = value; + } + + // + // Bullish Rejection Bar ... + + /** + * Get Bullish Rejection Bar Width ... + * + * @return ( int ) + */ + int BullishRejectionBarWidth() + { + return mBullishRejectionBarWidth; + } + + /** + * Set Bullish Rejection Bar Width ... + * + * @param value: Integer ... + */ + void BullishRejectionBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishRejectionBarWidth = value; + } + + /** + * Get Bullish Rejection Bar Arrow Code ... + * + * @return ( int ) + */ + int BullishRejectionBarArrow() + { + return mBullishRejectionBarArrow; + } + + /** + * Set Bullish Rejection Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BullishRejectionBarArrow(int value) + { + // + mBullishRejectionBarArrow = value; + } + + /** + * Get Bullish Rejection Bar Color ... + * + * @return ( color ) + */ + color BullishRejectionBarColor() + { + return mBullishRejectionBarColor; + } + + /** + * Set Bullish Rejection Bar Color ... + * + * @param value: Color ... + */ + void BullishRejectionBarColor(color value) + { + mBullishRejectionBarColor = value; + } + + // + // Bearish Rejection Bar ... + + /** + * Get Bearish Rejection Bar Width ... + * + * @return ( int ) + */ + int BearishRejectionBarWidth() + { + return mBearishRejectionBarWidth; + } + + /** + * Set Bearish Rejection Bar Width ... + * + * @param value: Integer ... + */ + void BearishRejectionBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishRejectionBarWidth = value; + } + + /** + * Get Bearish Rejection Bar Arrow Code ... + * + * @return ( int ) + */ + int BearishRejectionBarArrow() + { + return mBearishRejectionBarArrow; + } + + /** + * Set Bearish Rejection Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BearishRejectionBarArrow(int value) + { + // + mBearishRejectionBarArrow = value; + } + + /** + * Get Bearish Rejection Bar Color ... + * + * @return ( color ) + */ + color BearishRejectionBarColor() + { + return mBearishRejectionBarColor; + } + + /** + * Set Bearish Rejection Bar Color ... + * + * @param value: Color ... + */ + void BearishRejectionBarColor(color value) + { + mBearishRejectionBarColor = value; + } + + // + // Supply Zone ... + + /** + * Get Fill Supply Zone ... + * + * @return ( bool ) + */ + bool SupplyZoneFill() + { + return mSupplyZoneFill; + } + + /** + * Set Fill Supply Zone ... + * + * @param value: Boolean ... + */ + void SupplyZoneFill(bool value) + { + mSupplyZoneFill = value; + } + + /** + * Get Supply Zone Width ... + * + * @return ( int ) + */ + int SupplyZoneWidth() + { + return mSupplyZoneWidth; + } + + /** + * Set Supply Zone Width ... + * + * @param value: Integer ... + */ + void SupplyZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupplyZoneWidth = value; + } + + /** + * Get Supply Zone Color ... + * + * @return ( color ) + */ + color SupplyZoneColor() + { + return mSupplyZoneColor; + } + + /** + * Set Supply Zone Color ... + * + * @param value: Color ... + */ + void SupplyZoneColor(color value) + { + mSupplyZoneColor = value; + } + + /** + * Get Supply Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE SupplyZoneStyle() + { + return mSupplyZoneStyle; + } + + /** + * Set Supply Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupplyZoneStyle(ENUM_LINE_STYLE value) + { + mSupplyZoneStyle = value; + } + + // + // Demand Zone ... + + /** + * Get Fill Demand Zone ... + * + * @return ( bool ) + */ + bool DemandZoneFill() + { + return mDemandZoneFill; + } + + /** + * Set Fill Demand Zone ... + * + * @param value: Boolean ... + */ + void DemandZoneFill(bool value) + { + mDemandZoneFill = value; + } + + /** + * Get Demand Zone Width ... + * + * @return ( int ) + */ + int DemandZoneWidth() + { + return mDemandZoneWidth; + } + + /** + * Set Demand Zone Width ... + * + * @param value: Integer ... + */ + void DemandZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mDemandZoneWidth = value; + } + + /** + * Get Demand Zone Color ... + * + * @return ( color ) + */ + color DemandZoneColor() + { + return mDemandZoneColor; + } + + /** + * Set Demand Zone Color ... + * + * @param value: Color ... + */ + void DemandZoneColor(color value) + { + mDemandZoneColor = value; + } + + /** + * Get Demand Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE DemandZoneStyle() + { + return mDemandZoneStyle; + } + + /** + * Set Demand Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void DemandZoneStyle(ENUM_LINE_STYLE value) + { + mDemandZoneStyle = value; + } + + // + // Resistance Zone ... + + /** + * Get Fill Resistance Zone ... + * + * @return ( bool ) + */ + bool ResistanceZoneFill() + { + return mResistanceZoneFill; + } + + /** + * Set Fill Resistance Zone ... + * + * @param value: Boolean ... + */ + void ResistanceZoneFill(bool value) + { + mResistanceZoneFill = value; + } + + /** + * Get Resistance Zone Width ... + * + * @return ( int ) + */ + int ResistanceZoneWidth() + { + return mResistanceZoneWidth; + } + + /** + * Set Resistance Zone Width ... + * + * @param value: Integer ... + */ + void ResistanceZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mResistanceZoneWidth = value; + } + + /** + * Get Resistance Zone Color ... + * + * @return ( color ) + */ + color ResistanceZoneColor() + { + return mResistanceZoneColor; + } + + /** + * Set Resistance Zone Color ... + * + * @param value: Color ... + */ + void ResistanceZoneColor(color value) + { + mResistanceZoneColor = value; + } + + /** + * Get Resistance Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE ResistanceZoneStyle() + { + return mResistanceZoneStyle; + } + + /** + * Set Resistance Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ResistanceZoneStyle(ENUM_LINE_STYLE value) + { + mResistanceZoneStyle = value; + } + + // + // Support Zone ... + + /** + * Get Fill Support Zone ... + * + * @return ( bool ) + */ + bool SupportZoneFill() + { + return mSupportZoneFill; + } + + /** + * Set Fill Support Zone ... + * + * @param value: Boolean ... + */ + void SupportZoneFill(bool value) + { + mSupportZoneFill = value; + } + + /** + * Get Support Zone Width ... + * + * @return ( int ) + */ + int SupportZoneWidth() + { + return mSupportZoneWidth; + } + + /** + * Set Support Zone Width ... + * + * @param value: Integer ... + */ + void SupportZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupportZoneWidth = value; + } + + /** + * Get Support Zone Color ... + * + * @return ( color ) + */ + color SupportZoneColor() + { + return mSupportZoneColor; + } + + /** + * Set Support Zone Color ... + * + * @param value: Color ... + */ + void SupportZoneColor(color value) + { + mSupportZoneColor = value; + } + + /** + * Get Support Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE SupportZoneStyle() + { + return mSupportZoneStyle; + } + + /** + * Set Support Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupportZoneStyle(ENUM_LINE_STYLE value) + { + mSupportZoneStyle = value; + } + + // + // Bullish Order Block ... + + /** + * Get Fill Bullish Order Block ... + * + * @return ( bool ) + */ + bool BullishOrderBlockFill() + { + return mBullishOrderBlockFill; + } + + /** + * Set Fill Bullish Order Block ... + * + * @param value: Boolean ... + */ + void BullishOrderBlockFill(bool value) + { + mBullishOrderBlockFill = value; + } + + /** + * Get Bullish Order Block Width ... + * + * @return ( int ) + */ + int BullishOrderBlockWidth() + { + return mBullishOrderBlockWidth; + } + + /** + * Set Bullish Order Block Width ... + * + * @param value: Integer ... + */ + void BullishOrderBlockWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishOrderBlockWidth = value; + } + + /** + * Get Bullish Order Block Color ... + * + * @return ( color ) + */ + color BullishOrderBlockColor() + { + return mBullishOrderBlockColor; + } + + /** + * Set Bullish Order Block Color ... + * + * @param value: Color ... + */ + void BullishOrderBlockColor(color value) + { + mBullishOrderBlockColor = value; + } + + /** + * Get Bullish Order Block Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BullishOrderBlockStyle() + { + return mBullishOrderBlockStyle; + } + + /** + * Set Bullish Order Block Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BullishOrderBlockStyle(ENUM_LINE_STYLE value) + { + mBullishOrderBlockStyle = value; + } + + // + // Bearish Order Block ... + + /** + * Get Fill Bearish Order Block ... + * + * @return ( bool ) + */ + bool BearishOrderBlockFill() + { + return mBearishOrderBlockFill; + } + + /** + * Set Fill Bearish Order Block ... + * + * @param value: Boolean ... + */ + void BearishOrderBlockFill(bool value) + { + mBearishOrderBlockFill = value; + } + + /** + * Get Bearish Order Block Width ... + * + * @return ( int ) + */ + int BearishOrderBlockWidth() + { + return mBearishOrderBlockWidth; + } + + /** + * Set Bearish Order Block Width ... + * + * @param value: Integer ... + */ + void BearishOrderBlockWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishOrderBlockWidth = value; + } + + /** + * Get Bearish Order Block Color ... + * + * @return ( color ) + */ + color BearishOrderBlockColor() + { + return mBearishOrderBlockColor; + } + + /** + * Set Bearish Order Block Color ... + * + * @param value: Color ... + */ + void BearishOrderBlockColor(color value) + { + mBearishOrderBlockColor = value; + } + + /** + * Get Bearish Order Block Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BearishOrderBlockStyle() + { + return mBearishOrderBlockStyle; + } + + /** + * Set Bearish Order Block Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BearishOrderBlockStyle(ENUM_LINE_STYLE value) + { + mBearishOrderBlockStyle = value; + } + + // + // Bullish FVG ... + + /** + * Get Fill Bullish FVG ... + * + * @return ( bool ) + */ + bool BullishFVGFill() + { + return mBullishFVGFill; + } + + /** + * Set Fill Bullish FVG ... + * + * @param value: Boolean ... + */ + void BullishFVGFill(bool value) + { + mBullishFVGFill = value; + } + + /** + * Get Bullish FVG Width ... + * + * @return ( int ) + */ + int BullishFVGWidth() + { + return mBullishFVGWidth; + } + + /** + * Set Bullish FVG Width ... + * + * @param value: Integer ... + */ + void BullishFVGWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishFVGWidth = value; + } + + /** + * Get Bullish FVG Color ... + * + * @return ( color ) + */ + color BullishFVGColor() + { + return mBullishFVGColor; + } + + /** + * Set Bullish FVG Color ... + * + * @param value: Color ... + */ + void BullishFVGColor(color value) + { + mBullishFVGColor = value; + } + + /** + * Get Bullish FVG Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BullishFVGStyle() + { + return mBullishFVGStyle; + } + + /** + * Set Bullish FVG Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BullishFVGStyle(ENUM_LINE_STYLE value) + { + mBullishFVGStyle = value; + } + + // + // Bearish FVG ... + + /** + * Get Fill Bearish FVG ... + * + * @return ( bool ) + */ + bool BearishFVGFill() + { + return mBearishFVGFill; + } + + /** + * Set Fill Bearish FVG ... + * + * @param value: Boolean ... + */ + void BearishFVGFill(bool value) + { + mBearishFVGFill = value; + } + + /** + * Get Bearish FVG Width ... + * + * @return ( int ) + */ + int BearishFVGWidth() + { + return mBearishFVGWidth; + } + + /** + * Set Bearish FVG Width ... + * + * @param value: Integer ... + */ + void BearishFVGWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishFVGWidth = value; + } + + /** + * Get Bearish FVG Color ... + * + * @return ( color ) + */ + color BearishFVGColor() + { + return mBearishFVGColor; + } + + /** + * Set Bearish FVG Color ... + * + * @param value: Color ... + */ + void BearishFVGColor(color value) + { + mBearishFVGColor = value; + } + + /** + * Get Bearish FVG Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BearishFVGStyle() + { + return mBearishFVGStyle; + } + + /** + * Set Bearish FVG Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BearishFVGStyle(ENUM_LINE_STYLE value) + { + mBearishFVGStyle = value; + } + + // + // Virtuals ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + BarWidth(1); + BarBearishColor(clrRed); + BarBullishColor(clrLime); + BarFillBody(false); + BarFillHighShadow(false); + BarFillLowShadow(false); + BarBodyStyle(STYLE_DOT); + BarLowShadowStyle(STYLE_DOT); + BarHighShadowStyle(STYLE_DOT); + + // + int arrowWidth = 1; + + // + SwingLowArrow(108); + SwingLowColor(clrAqua); + SwingLowWidth(arrowWidth); + + // + SwingHighArrow(108); + SwingHighWidth(arrowWidth); + SwingHighColor(clrMagenta); + + // + arrowWidth++; + + // + BullishMomentumBarArrow(225); + BullishMomentumBarWidth(arrowWidth); + BullishMomentumBarColor(clrAqua); + + // + BearishMomentumBarArrow(226); + BearishMomentumBarWidth(arrowWidth); + BearishMomentumBarColor(clrMagenta); + + // + arrowWidth++; + + // + BullishRejectionBarArrow(217); + BullishRejectionBarWidth(arrowWidth); + BullishRejectionBarColor(clrAqua); + + // + BearishRejectionBarArrow(218); + BearishRejectionBarWidth(arrowWidth); + BearishRejectionBarColor(clrMagenta); + + // + SupportZoneFill(false); + SupportZoneWidth(1); + SupportZoneStyle(STYLE_DOT); + SupportZoneColor(clrLime); + + // + ResistanceZoneFill(false); + ResistanceZoneWidth(1); + ResistanceZoneStyle(STYLE_DOT); + ResistanceZoneColor(clrRed); + + // + SupplyZoneFill(false); + SupplyZoneWidth(1); + SupplyZoneStyle(STYLE_DOT); + SupplyZoneColor(clrRed); + + // + DemandZoneFill(false); + DemandZoneWidth(1); + DemandZoneStyle(STYLE_DOT); + DemandZoneColor(clrGreen); + + // + BullishOrderBlockFill(false); + BullishOrderBlockWidth(1); + BullishOrderBlockStyle(STYLE_DASHDOT); + BullishOrderBlockColor(clrLime); + + // + BearishOrderBlockFill(false); + BearishOrderBlockWidth(1); + BearishOrderBlockStyle(STYLE_DASHDOT); + BearishOrderBlockColor(clrRed); + + // + BullishFVGFill(false); + BullishFVGWidth(1); + BullishFVGStyle(STYLE_DOT); + BullishFVGColor(clrLime); + + // + BearishFVGFill(false); + BearishFVGWidth(1); + BearishFVGStyle(STYLE_DOT); + BearishFVGColor(clrRed); + + // + // Add Default TickZone Specs ... + bool isSpecsInited = false; + bool fillTickZone = false; + XTickZoneLevelSpecs specs10; + isSpecsInited = specs10.Init( + 10, + clrWhite, + clrWhite, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs10); + } + + // + XTickZoneLevelSpecs specs20; + isSpecsInited = specs20.Init( + 20, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs20); + } + + // + XTickZoneLevelSpecs specs30; + isSpecsInited = specs30.Init( + 30, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs30); + } + + // + XTickZoneLevelSpecs specs40; + isSpecsInited = specs40.Init( + 40, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs40); + } + + // + XTickZoneLevelSpecs specs50; + isSpecsInited = specs50.Init( + 50, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs50); + } + + // + XTickZoneLevelSpecs specs60; + isSpecsInited = specs60.Init( + 60, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs60); + } + + // + XTickZoneLevelSpecs specs70; + isSpecsInited = specs70.Init( + 70, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs70); + } + + // + XTickZoneLevelSpecs specs80; + isSpecsInited = specs80.Init( + 80, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs80); + } + + // + XTickZoneLevelSpecs specs90; + isSpecsInited = specs90.Init( + 90, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs90); + } + + // + XTickZoneLevelSpecs specs100; + isSpecsInited = specs100.Init( + 100, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs100); + } + + // + } + + // + // Object Creators ... + + // + // Swings ... + + /** + * Create Swing High Object ... + * + * @param swing: XCSwing instance ... + * @param object: XCSwingHighObject pointer ... + * + * @return ( bool ) + */ + bool CreateSwingHigh( + XCSwing &swing, + XCSwingHighObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + swing.IsValid() && + swing.IsSwingHigh(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = SwingHighArrow(); + int width = SwingHighWidth(); + color crl = SwingHighColor(); + + // + object = new XCSwingHighObject(); + result = object.Create( + chartID, + window, + arrow, + swing, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + /** + * Create Swing Low Object ... + * + * @param swing: XCSwing instance ... + * @param object: XCSwingLowObject pointer ... + * + * @return ( bool ) + */ + bool CreateSwingLow( + XCSwing &swing, + XCSwingLowObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + swing.IsValid() && + swing.IsSwingLow(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = SwingLowArrow(); + int width = SwingLowWidth(); + color crl = SwingLowColor(); + + // + object = new XCSwingLowObject(); + result = object.Create( + chartID, + window, + arrow, + swing, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + // + // Momentum Bars ... + + /** + * Create Bullish Momentum Bar Object ... + * + * @param momentumBar: XCMomentumBar instance ... + * @param object: XCBullishMomentumObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishMomentumBar( + XCMomentumBar &momentumBar, + XCBullishMomentumBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + momentumBar.IsValid() && + momentumBar.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BullishMomentumBarArrow(); + int width = BullishMomentumBarWidth(); + color crl = BullishMomentumBarColor(); + + // + object = new XCBullishMomentumBarObject(); + result = object.Create( + chartID, + window, + arrow, + momentumBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + /** + * Create Bearish Momentum Bar Object ... + * + * @param momentumBar: XCMomentumBar instance ... + * @param object: XCBearishMomentumObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishMomentumBar( + XCMomentumBar &momentumBar, + XCBearishMomentumBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + momentumBar.IsValid() && + momentumBar.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BearishMomentumBarArrow(); + int width = BearishMomentumBarWidth(); + color crl = BearishMomentumBarColor(); + + // + object = new XCBearishMomentumBarObject(); + result = object.Create( + chartID, + window, + arrow, + momentumBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + // + // Rejection Bars ... + + /** + * Create Bullish Rejection Bar Object ... + * + * @param momentumBar: XCRejectionBar instance ... + * @param object: XCBullishRejectionObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishRejectionBar( + XCRejectionBar &rejectionBar, + XCBullishRejectionBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + rejectionBar.IsValid() && + rejectionBar.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BullishRejectionBarArrow(); + int width = BullishRejectionBarWidth(); + color crl = BullishRejectionBarColor(); + + // + object = new XCBullishRejectionBarObject(); + result = object.Create( + chartID, + window, + arrow, + rejectionBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + /** + * Create Bearish Rejection Bar Object ... + * + * @param rejectionBar: XCRejectionBar instance ... + * @param object: XCBearishRejectionObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishRejectionBar( + XCRejectionBar &rejectionBar, + XCBearishRejectionBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + rejectionBar.IsValid() && + rejectionBar.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BearishRejectionBarArrow(); + int width = BearishRejectionBarWidth(); + color crl = BearishRejectionBarColor(); + + // + object = new XCBearishRejectionBarObject(); + result = object.Create( + chartID, + window, + arrow, + rejectionBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + // + // Support and Resistance ... + + /** + * Create Support Object ... + * + * @param zone: XCSupportZone instance ... + * @param object: XCSupportZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupportZone( + XCSupportZone &zone, + XCSupportZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupportZoneFill(); + int width = SupportZoneWidth(); + color crl = SupportZoneColor(); + ENUM_LINE_STYLE style = SupportZoneStyle(); + + // + object = new XCSupportZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Resistance Object ... + * + * @param zone: XCResistanceZone instance ... + * @param object: XCResistanceZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateResistanceZone( + XCResistanceZone &zone, + XCResistanceZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = ResistanceZoneFill(); + int width = ResistanceZoneWidth(); + color crl = ResistanceZoneColor(); + ENUM_LINE_STYLE style = ResistanceZoneStyle(); + + // + object = new XCResistanceZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + // + // Supply and Demand Zones ... + + /** + * Create Supply Object ... + * + * @param zone: XCSupplyZone instance ... + * @param object: XCSupplyZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupplyZone( + XCSupplyZone &zone, + XCSupplyZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupplyZoneFill(); + int width = SupplyZoneWidth(); + color crl = SupplyZoneColor(); + ENUM_LINE_STYLE style = SupplyZoneStyle(); + + // + object = new XCSupplyZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Demand Object ... + * + * @param zone: XCDemandZone instance ... + * @param object: XCDemandZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateDemandZone( + XCDemandZone &zone, + XCDemandZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = DemandZoneFill(); + int width = DemandZoneWidth(); + color crl = DemandZoneColor(); + ENUM_LINE_STYLE style = DemandZoneStyle(); + + // + object = new XCDemandZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + // + // Order Blocks ... + + /** + * Create Bullish Order Block Object ... + * + * @param zone: XCOrderBlock instance ... + * @param object: XCBullishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishOrderBlock( + XCOrderBlock &zone, + XCBullishOrderBlockObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BullishOrderBlockFill(); + int width = BullishOrderBlockWidth(); + color crl = BullishOrderBlockColor(); + ENUM_LINE_STYLE style = BullishOrderBlockStyle(); + + // + object = new XCBullishOrderBlockObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Bearish Order Block Object ... + * + * @param zone: XCOrderBlock instance ... + * @param object: XCBearishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishOrderBlock( + XCOrderBlock &zone, + XCBearishOrderBlockObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BearishOrderBlockFill(); + int width = BearishOrderBlockWidth(); + color crl = BearishOrderBlockColor(); + ENUM_LINE_STYLE style = BearishOrderBlockStyle(); + + // + object = new XCBearishOrderBlockObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + bool CreateOrderBlock( + XCOrderBlock &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishOrderBlockObject *iObj; + result = CreateBullishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishOrderBlockObject *iObj; + result = CreateBearishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + + // + // Fair Value Gaps ... + + /** + * Create Bullish Fair Value Gap Object ... + * + * @param zone: XCFVG instance ... + * @param object: XCBullishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishFairValueGap( + XCFVG &zone, + XCBullishFairValueGapObject *&object // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BullishFVGFill(); + int width = BullishFVGWidth(); + color crl = BullishFVGColor(); + ENUM_LINE_STYLE style = BullishFVGStyle(); + + // + object = new XCBullishFairValueGapObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Bearish Fair Value Gap Object ... + * + * @param zone: XCFVG instance ... + * @param object: XCBearishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishFairValueGap( + XCFVG &zone, + XCBearishFairValueGapObject *&object // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BearishFVGFill(); + int width = BearishFVGWidth(); + color crl = BearishFVGColor(); + ENUM_LINE_STYLE style = BearishFVGStyle(); + + // + object = new XCBearishFairValueGapObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + bool CreateFairValueGap( + XCFVG &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishFairValueGapObject *iObj; + result = CreateBullishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishFairValueGapObject *iObj; + result = CreateBearishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + + // + // Ticks Zone ... + + /** + * Add Tick Zone Draw Specifications ... + * + * @param specs: XTickZoneLevelSpecs instance ... + */ + void AddTickZoneLevelSpecs( + XTickZoneLevelSpecs &specs // + ) + { + // + if (!specs.IsValid()) + { + return; + } + + // + bool isExists = false; + int count = ArraySize(mTicksZoneSpecs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XTickZoneLevelSpecs iSpec = mTicksZoneSpecs[i]; + + // + isExists = specs.percent == iSpec.percent; + if (isExists) + { + break; + } + } + } + if (isExists) + { + return; + } + + // + AddRef( + specs, + mTicksZoneSpecs // + ); + } + + /** + * Draw Specified Ticker Zone ... + * + * @param zone: XCTicksZone instance Specified Ticker Zone ... + * @param object: XCTicksZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateTicksZone( + XCTicksZone &zone, + XCTicksZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTicksZoneObject(); + result = object.Create( + chartID, + window, + zone, + mTicksZoneSpecs, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Create Consolidation Zone Object ... + * + * @param zone: XConsolidationZone instance Reference ... + * + * @return ( bool ) + */ + bool CreateConsolidationZone( + XConsolidationZone &zone, + XCConsolidationZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + color czColor = IsBullish(zone.dir) + ? BarBullishColor() + : BarBearishColor(); + + // + object = new XCConsolidationZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (result) + { + object.ZoneColor(czColor); + } + + // + return result; + } + + /** + * Create Bar Object ... + * + * @param bar: XOHCL instance Reference ... + * @param object: XCOHCLObject pointer Reference .. + * @param to: Datetime ... + * + * @return ( bool ) + */ + bool CreateBar( + XOHCL &bar, + XCOHCLObject *&object, + datetime to = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int width = BarWidth(); + + // + color mBullishColor = BarBullishColor(); + color mBearishColor = BarBearishColor(); + + // + bool fillBody = BarFillBody(); + bool fillHighShadow = BarFillHighShadow(); + bool fillLowShadow = BarFillLowShadow(); + + // + ENUM_LINE_STYLE bodyStyle = BarBodyStyle(); + ENUM_LINE_STYLE highShadowStyle = BarHighShadowStyle(); + ENUM_LINE_STYLE lowShadowStyle = BarLowShadowStyle(); + + // + object = new XCOHCLObject(); + result = object.Create( + chartID, + window, + bar, + to, + prefix // + ); + if (result) + { + // + // Apply Styling ... + + // + object.BodyWidth(width); + object.LowShadowWidth(width); + object.HighShadowWidth(width); + + // + object.BodyStyle(bodyStyle); + object.LowShadowStyle(lowShadowStyle); + object.HighShadowStyle(highShadowStyle); + + // + bool isBullish = bar.IsBullish(); + if (isBullish) + { + // + object.BodyColor(mBullishColor); + object.LowShadowColor(mBullishColor); + object.HighShadowColor(mBullishColor); + } + else + { + // + object.BodyColor(mBearishColor); + object.LowShadowColor(mBearishColor); + object.HighShadowColor(mBearishColor); + } + + // + object.BodyFill(fillBody); + object.HighShadowFill(fillHighShadow); + object.LowShadowFill(fillLowShadow); + } + + // + return result; + } + + /** + * Create Bar Arrow Object ... + * + * @param bar: XOHCL instance Reference ... + * @param priceType: ENUM_X_PRICE member ... + * @param arrow: int, Arrow Code ... + * @param clr: color, Arro Color ... + * @param width: int, Arrow Width ... + * @param anchor: ENUM_ARROW_ANCHOR, anchor of Arrow ... + * @param name: string, name of Arrow ... + * + * @return ( bool ) + */ + bool CreateBarArrow( + XOHCL &bar, + XCBarArrowObject *&object, + ENUM_X_PRICE priceType, + int arrow = 159, + color clr = clrYellow, + int width = 3, + ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, + string name = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + string barTag = bar.GetTag(name); + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + color mBullishColor = BarBullishColor(); + color mBearishColor = BarBearishColor(); + + // + prefix = + (IsValid(prefix) + ? prefix + "_" + : prefix) + + barTag; + + // + object = new XCBarArrowObject(); + result = object + .CreateByBar( + chartID, + prefix, + window, + arrow, + bar, + priceType // + ); + if (result) + { + // + object.ArrowColor(clr); + object.ArrowWidth(width); + } + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param upper: Double ... + * @param lower: Double ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool CreateBox( + XCBoxObject *&object, + string name, + double upper, + double lower, + datetime from, + datetime to, + color clr = clrYellowGreen, + int width = 1, + bool fill = false, + ENUM_LINE_STYLE style = STYLE_SOLID // + ) + { + // + bool result = false; + + // + object = NULL; + + // + to = NormalizeTime(to); + + // + string dateStr = ToFormatString(from) + "|" + ToFormatString(to); + string dateMD5 = ToMD5(dateStr); + if (!IsValid(name)) + { + // + name = "XBox_" + + ToString(upper) + "_" + + ToString(lower) + "_" + + dateMD5; + } + + // + result = + upper > 0 && + lower > 0 && + to > from && + IsValid(to) && + IsValid(name) && + IsValid(from) && + upper > lower; + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCBoxObject(); + result = object.Create( + chartID, + window, + name, + upper, + lower, + from, + to, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.BoxColor(clr); + object.BoxFill(fill); + object.BoxWidth(width); + object.BoxStyle(style); + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param box: XBoxZone instance Reference ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool DrawBox( + XBoxZone &box, + XCBoxObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int width = 1; + bool fill = false; + color clr = + box.IsBullish() + ? BullishFVGColor() + : BearishFVGColor(); + ENUM_LINE_STYLE style = STYLE_DASHDOTDOT; + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param box: XBoxZone instance Reference ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool CreateBox( + XBoxZone &box, + XCBoxObject *&object, + color clr = clrYellowGreen, + int width = 1, + bool fill = false, + ENUM_LINE_STYLE style = STYLE_SOLID // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal instance ... + */ + bool DrawSignal( + XSignal &signal, + XCSignalObject *&object, + int length = 3 // + ) + { + // + bool result = false; + + // + object = NULL; + length = NormalizeInt(length, 3); + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCSignalObject(); + result = object.Create( + chartID, + window, + signal, + length, + prefix // + ); + if (!result) + { + return result; + } + + // + object.TPWidth(1); + object.TPColor(clrGreen); + object.TPWidth(STYLE_DOT); + + // + object.SLWidth(1); + object.SLColor(clrRed); + object.SLWidth(STYLE_DOT); + + // + object.TargetWidth(1); + object.TargetColor(clrLightBlue); + object.TargetWidth(STYLE_DOT); + + // + object.EntryWidth(1); + object.EntryColor(clrYellow); + object.EntryWidth(STYLE_DOT); + + // + return result; + } + + /** + * Draw Signal Box ... + * + * @param box: XSignalBox instance Reference ... + * @param objects: XCBaseObject pointer instance Reference ... + * + * @return ( bool ) + */ + bool DrawSignalBox( + XSignalBox &box, + XCBaseObject *&objects[], + color clr = CLR_NONE // + ) + { + // + bool result = false; + + // + Clean(objects); + + // + bool has = false; + bool hasColor = clr != CLR_NONE; + + // + // Order Block ... + if (box.ob.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + box.ob, + iObj // + ); + if (has) + { + // + iObj.BoxStyle(STYLE_DASH); + + // + if (hasColor) + { + iObj.BoxColor(clr); + } + + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + } + + // + // Fair Value Gap ... + if (box.fvg.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + box.fvg, + iObj // + ); + if (has) + { + // + iObj.BoxStyle(STYLE_SOLID); + + // + if (hasColor) + { + iObj.BoxColor(clr); + } + + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + } + + // + // Sharp Zone ... + if (box.sharp.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + box.sharp, + iObj // + ); + if (has) + { + // + iObj.BoxStyle(STYLE_DOT); + + // + if (hasColor) + { + iObj.BoxColor(clr); + } + + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + } + + // + result = HasChild(objects); + + // + return result; + } + + /** + * Draw Specified POI State ... + * + * @param state: XPOIState instance Reference ... + * @param drawnObjects: CArrayObj instance for Holding Drawn Objects ... + * @param drawTicksZone: Boolean ... + * @param ignoreSwingHighs: Boolean ... + * @param ignoreSwingLows: Boolean ... + * @param ignoreSupportZones: Boolean ... + * @param ignoreResistanceZones: Boolean ... + * @param ignoreSupplyZones: Boolean ... + * @param ignoreDemandZones: Boolean ... + * @param ignoreBullishOrderBlocks: Boolean ... + * @param ignoreBearishOrderBlocks: Boolean ... + * @param ignoreBullishFairValueGaps: Boolean ... + * @param ignoreBearishFairValueGaps: Boolean ... + * @param ignoreBullishRejectionBars: Boolean ... + * @param ignoreBearishRejectionBars: Boolean ... + * @param ignoreBullishMomentumBars: Boolean ... + * @param ignoreBearishMomentumBars: Boolean ... + */ + int DrawState( + XPOIState &state, + XCBaseObject *&drawnObjects[], + // + // Bullish ... + bool ignoreSwingLows = false, + bool ignoreDemandZones = false, + bool ignoreSupportZones = false, + bool ignoreBullishSharps = false, + bool ignoreBullishSpikes = false, + bool ignoreBullishPullbacks = false, + bool ignoreBullishMomentums = false, + bool ignoreBullishRejections = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBullishConsolidationZones = false, + // + // Bearish ... + bool ignoreSwingHighs = false, + bool ignoreSupplyZones = false, + bool ignoreResistanceZones = false, + bool ignoreBearishSharps = false, + bool ignoreBearishSpikes = false, + bool ignoreBearishPullbacks = false, + bool ignoreBearishMomentums = false, + bool ignoreBearishRejections = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBearishConsolidationZones = false // + ) + { + // + int result = 0; + + // + if (!state.IsValid() || + !state.HasChild()) + { + return result; + } + + // + Clean(drawnObjects); + + // + // Swings ... + + // + // SwingHighs ... + if (!ignoreSwingHighs) + { + // + int count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = state.swingHighs[i]; + XCSwingHighObject *iObj; + + // + bool isCreated = CreateSwingHigh( + iSwing, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // SwingLows ... + if (!ignoreSwingLows) + { + // + int count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = state.swingLows[i]; + XCSwingLowObject *iObj; + + // + bool isCreated = CreateSwingLow( + iSwing, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Support / Resistance ... + + // + // SupportZones ... + if (!ignoreSupportZones) + { + // + int count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = state.supportZones[i]; + XCSupportZoneObject *iObj; + + // + bool isCreated = CreateSupportZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // ResistanceZones ... + if (!ignoreResistanceZones) + { + // + int count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = state.resistanceZones[i]; + XCResistanceZoneObject *iObj; + + // + bool isCreated = CreateResistanceZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Supply / Demand ... + + // + // SupplyZones ... + if (!ignoreSupplyZones) + { + // + int count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + XCSupplyZoneObject *iObj; + + // + bool isCreated = CreateSupplyZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // DemandZones ... + if (!ignoreDemandZones) + { + // + int count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + XCDemandZoneObject *iObj; + + // + bool isCreated = CreateDemandZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // BullishOrderBlocks ... + if (!ignoreBullishOrderBlocks) + { + // + int count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + XCBullishOrderBlockObject *iObj; + + // + bool isCreated = CreateBullishOrderBlock( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishOrderBlocks ... + if (!ignoreBearishOrderBlocks) + { + // + int count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + XCBearishOrderBlockObject *iObj; + + // + bool isCreated = CreateBearishOrderBlock( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // BullishFairValueGaps ... + if (!ignoreBullishFairValueGaps) + { + // + int count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = state.bullishFairValueGaps[i]; + XCBullishFairValueGapObject *iObj; + + // + bool isCreated = CreateBullishFairValueGap( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishFairValueGaps ... + if (!ignoreBearishFairValueGaps) + { + // + int count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = state.bearishFairValueGaps[i]; + XCBearishFairValueGapObject *iObj; + + // + bool isCreated = CreateBearishFairValueGap( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Rejections ... + + // + // BullishRejectionBars ... + if (!ignoreBullishRejections) + { + // + int count = state.CountBullishRejections(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iBar = state.bullishRejections[i]; + XCBullishRejectionBarObject *iObj; + + // + bool isCreated = CreateBullishRejectionBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishRejectionBars ... + if (!ignoreBearishRejections) + { + // + int count = state.CountBearishRejections(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iBar = state.bearishRejections[i]; + XCBearishRejectionBarObject *iObj; + + // + bool isCreated = CreateBearishRejectionBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Momentums ... + + // + // BullishMomentumBars ... + if (!ignoreBullishMomentums) + { + // + int count = state.CountBullishMomentums(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iBar = state.bullishMomentums[i]; + XCBullishMomentumBarObject *iObj; + + // + bool isCreated = CreateBullishMomentumBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishMomentumBars ... + if (!ignoreBearishMomentums) + { + // + int count = state.CountBearishMomentums(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iBar = state.bearishMomentums[i]; + XCBearishMomentumBarObject *iObj; + + // + bool isCreated = CreateBearishMomentumBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Pullbacks ... + + // + // Bullish ... + if (!ignoreBullishPullbacks) + { + // + int count = state.CountBullishPullbacks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bullishPullbacks[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish ... + if (!ignoreBearishPullbacks) + { + // + int count = state.CountBearishPullbacks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bearishPullbacks[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Consolidation Zones ... + + // + // Bullish Consolidation Zones ... + if (!ignoreBullishConsolidationZones) + { + // + int count = state.CountBullishConsolidationZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCConsolidationZoneObject *iObj; + bool isCreated = CreateConsolidationZone( + state.bullishConsolidationZones[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish Consolidation Zones ... + if (!ignoreBearishConsolidationZones) + { + // + int count = state.CountBearishConsolidationZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCConsolidationZoneObject *iObj; + bool isCreated = CreateConsolidationZone( + state.bearishConsolidationZones[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Spikes ... + + // + // Bullish ... + if (!ignoreBullishSpikes) + { + // + int count = state.CountBullishSpikes(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bullishSpikes[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish ... + if (!ignoreBearishSpikes) + { + // + int count = state.CountBearishSpikes(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bearishSpikes[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Sharps ... + + // + // Bullish ... + if (!ignoreBullishSharps) + { + // + int count = state.CountBullishSharps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bullishSharps[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish ... + if (!ignoreBearishSharps) + { + // + int count = state.CountBearishSharps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bearishSharps[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + result = ArraySize(drawnObjects); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + string mPrefix; // Prefix of Created Objects ... + long mChartIdentification; // Chart Id ... + int mSubWindowIdentification; // Sub Window ... + + // + // XOHCL ... + int mBarWidth; // Bar Width ... + color mBarBullishColor; // Bar Bullish Color ... + color mBarBearishColor; // Bar Bearish Color ... + bool mBarFillHighShadow; // Fill Bar High Shadow ... + ENUM_LINE_STYLE mBarHighShadowStyle; // Bar High Shadow Style ... + bool mBarFillBody; // Fill Bar Body ... + ENUM_LINE_STYLE mBarBodyStyle; // Bar Body Style ... + bool mBarFillLowShadow; // Fill Bar Low Show ... + ENUM_LINE_STYLE mBarLowShadowStyle; // Bar Low Shadow Style ... + + // + // Swing Low ... + int mSwingLowWidth; // Swing Low Width ... + int mSwingLowArrow; // Swing Low Arrow Code ... + color mSwingLowColor; // Swing Low Color ... + + // + // Swing High ... + int mSwingHighWidth; // Swing High Width ... + int mSwingHighArrow; // Swing High Arrow Code ... + color mSwingHighColor; // Swing High Color ... + + // + // Bullish Momentum Bar ... + int mBullishMomentumBarWidth; // Bullish Momentum Bar Width ... + int mBullishMomentumBarArrow; // Bullish Momentum Bar Arrow Code ... + color mBullishMomentumBarColor; // Bullish Momentum Bar Color ... + + // + // Bearish Momentum Bar ... + int mBearishMomentumBarWidth; // Bearish Momentum Bar Width ... + int mBearishMomentumBarArrow; // Bearish Momentum Bar Arrow Code ... + color mBearishMomentumBarColor; // Bearish Momentum Bar Color ... + + // + // Bullish Rejection Bar ... + int mBullishRejectionBarWidth; // Bullish Rejection Bar High Width ... + int mBullishRejectionBarArrow; // Bullish Rejection Bar High Arrow Code ... + color mBullishRejectionBarColor; // Bullish Rejection Bar High Color ... + + // + // Bearish Rejection Bar ... + int mBearishRejectionBarWidth; // Bearish Rejection Bar Width ... + int mBearishRejectionBarArrow; // Bearish Rejection Bar Arrow Code ... + color mBearishRejectionBarColor; // Bearish Rejection Bar Color ... + + // + // Supply Zone ... + bool mSupplyZoneFill; // Fill Supply Zone ... + int mSupplyZoneWidth; // Supply Zone Width ... + color mSupplyZoneColor; // Supply Zone Color ... + ENUM_LINE_STYLE mSupplyZoneStyle; // Supply Zone Style ... + + // + // Demand Zone ... + bool mDemandZoneFill; // Fill Demand Zone ... + int mDemandZoneWidth; // Demand Zone Width ... + color mDemandZoneColor; // Demand Zone Color ... + ENUM_LINE_STYLE mDemandZoneStyle; // Demand Zone Style ... + + // + // Resistance Zone ... + bool mResistanceZoneFill; // Fill Resistance Zone ... + int mResistanceZoneWidth; // Resistance Zone Width ... + color mResistanceZoneColor; // Resistance Zone Color ... + ENUM_LINE_STYLE mResistanceZoneStyle; // Resistance Zone Style ... + + // + // Support Zone ... + bool mSupportZoneFill; // Fill Support Zone ... + int mSupportZoneWidth; // Support Zone Width ... + color mSupportZoneColor; // Support Zone Color ... + ENUM_LINE_STYLE mSupportZoneStyle; // Support Zone Style ... + + // + // Bullish Order Block ... + bool mBullishOrderBlockFill; // Fill Bullish Order Block ... + int mBullishOrderBlockWidth; // Bullish Order Block Width ... + color mBullishOrderBlockColor; // Bullish Order Block Color ... + ENUM_LINE_STYLE mBullishOrderBlockStyle; // Bullish Order Block Style ... + + // + // Bearish Order Block ... + bool mBearishOrderBlockFill; // Fill Bearish Order Block ... + int mBearishOrderBlockWidth; // Bearish Order Block Width ... + color mBearishOrderBlockColor; // Bearish Order Block Color ... + ENUM_LINE_STYLE mBearishOrderBlockStyle; // Bearish Order Block Style ... + + // + // Bullish FVG ... + bool mBullishFVGFill; // Fill Bullish FVG ... + int mBullishFVGWidth; // Bullish FVG Width ... + color mBullishFVGColor; // Bullish FVG Color ... + ENUM_LINE_STYLE mBullishFVGStyle; // Bullish FVG Style ... + + // + // Bearish FVG ... + bool mBearishFVGFill; // Fill Bearish FVG ... + int mBearishFVGWidth; // Bearish FVG Width ... + color mBearishFVGColor; // Bearish FVG Color ... + ENUM_LINE_STYLE mBearishFVGStyle; // Bearish FVG Style ... + + // + // Ticks Zone ... + XTickZoneLevelSpecs mTicksZoneSpecs[]; // Zone Draw Specifications ... + + // +}; \ No newline at end of file diff --git a/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..abde4f0 --- /dev/null +++ b/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.extensions.lib.mq5 @@ -0,0 +1,3807 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Extensions ... + +template +bool ToZone( + T *&source[], + XCZone *&dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + Add( + (XCZone *)item, + dest // + ); + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +bool ToBox( + T *&source[], + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + item // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +int GetOldest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetOldest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetYoungest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetYoungest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetLowest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetLowest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetHighest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetHighest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +bool IsSame( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSameAs(destBox); + + // + return result; +} + +template +bool IsSameDiff( + T *source, + F *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSame(destBox); + + // + return result; +} + +template +bool IsBelow( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsBelowDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAbove( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAboveDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsInside( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideOr( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox, + forceSideOut // + ); + + // + return result; +} + +template +bool IsInsideOrDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool FindIndex( + int &index, + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + XBoxZone itemBox; + result = ToBox( + itemBox, + item // + ); + if (!result) + { + return result; + } + + // + XBoxZone itemsBox[]; + result = ToBox( + items, + itemsBox // + ); + if (!result) + { + return result; + } + + // + result = FindBoxIndex( + index, + itemBox, + itemsBox // + ); + + // + return result; +} + +template +bool IsInside( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsInsideBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsAbove( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsAboveBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsBelow( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsBelowBox( + value, + sourceBox // + ); + + // + return result; +} + +/** + * Find Specified Box Index inside a Collection of Boxes ... + * + * @param box: XBoxZone instance Reference ... + * @param boxes: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +bool FindBoxIndex( + int &index, + XBoxZone &box, + XBoxZone &boxes[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(boxes); + result = box.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + bool isSame = box.IsSameAs(iBox); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Check a BaxHas Valid Place for Specified Bar ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * #param box: XBoxZone instance reference, Specified Box ... + * + * @return ( bool ) + */ +bool IsBoxPlaceValidForBar( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + box.IsBullish() + ? bar.low > box.upper + : bar.high < box.upper; + + // + return result; +} + +/** + * Check Source Box is Below Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxBelow( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.upper < dest.lower; + } + else + { + result = (source.upper < dest.lower || + source.upper >= dest.upper) && + source.lower < dest.lower; + } + + // + return result; +} + +/** + * Check Source Box is Above Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxAbove( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.lower > dest.upper; + } + else + { + result = (source.lower > dest.upper || + source.lower <= dest.upper) && + source.upper > dest.upper; + } + + // + return result; +} + +/** + * Check Source Box is Inside Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param forceSideOut: bool, force check Box has One Side Out ... + * @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ... + * + * @return ( bool ) + */ +bool IsBoxInside( + XBoxZone &source, + XBoxZone &dest, + bool forceSideOut = false, // + bool ignoreSideOut = true // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dest.dir); + + // + if (!forceSideOut) + { + // + if (ignoreSideOut) + { + // + result = source.lower >= dest.lower && + source.upper <= dest.upper; + } + else + { + result = source.lower >= dest.lower || + source.upper <= dest.upper; + } + } + else + { + // + bool hasSideIn = + isBullish + ? source.lower >= dest.lower + : source.upper <= dest.upper; + bool hasSideOut = + isBullish + ? source.upper >= dest.upper + : source.lower <= dest.lower; + result = + hasSideIn && + hasSideOut; + } + + // + return result; +} + +/** + * Detect source BoX is Inside Dest Box or Have a Side Out on it ... + * + * @param source: XBoxZone instance, source box which checks by dest ... + * @param dest: XBoxZone instance, dest Box which compares source with it ... + * + * @return ( bool ) + */ +bool IsBoxInsideOr( + XBoxZone &source, + XBoxZone &dest, + bool forceInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + bool isInside = + source.upper <= dest.upper && + source.upper >= dest.lower && + source.lower >= dest.lower && + source.lower <= dest.upper; + bool isUpperInside = + source.upper <= dest.upper && + source.upper >= dest.lower; + bool isLowerInside = + source.lower >= dest.lower && + source.lower <= dest.upper; + + // + result = + forceInside + ? isInside + : (isInside || + isLowerInside || + isUpperInside); + + // + return result; +} + +/** + * Check Value is Inside Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value <= box.upper && + value >= box.lower; + + // + return result; +} + +/** + * Check Bar is Inside Specified Box ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + bar.close <= box.upper && + bar.close >= box.lower; + + // + return result; +} + +/** + * Check Value is Above Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsAboveBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value > box.upper; + + // + return result; +} + +/** + * Check Value is Below Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsBelowBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value < box.lower; + + // + return result; +} + +/** + * Check a Box is Used or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxUsed( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + bool isTouched = false; + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + isTouched = + isInited && + (isBullish + ? iBar.low > box.upper + : iBar.high < box.lower); + if (!isTouched) + { + continue; + } + + // + iBar.Clean(); + break; + } + + // + result = isTouched; + + // + return result; +} + +/** + * Validate Box ... + * + * @param box: XBoxZone instance ... + * @param barIndex: int, Current Bar Index ... + * @param forPeriod: Testing Period ... + * + * @return ( bool ) + */ +bool IsBoxValid( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + return true; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int toIndex = iBarShift( + box.symbol, + forPeriod, + box.to // + ); + result = IsValidIndex(toIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < toIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.low > box.upper + : iBar.high < box.lower; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Check Box Breaked ... + * + * @param box: XBoxZone instance ... + * @param barIndex: int, Current Bar Index ... + * @param forPeriod: Testing Period ... + * + * @return ( bool ) + */ +bool IsBoxBreaked( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int toIndex = iBarShift( + box.symbol, + forPeriod, + box.to // + ); + result = IsValidIndex(toIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < toIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.high < box.lower + : iBar.low > box.upper; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Check a Box is Breaked or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxBreaked( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + bool isBreaked = false; + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + isBreaked = + isInited && + (isBullish + ? iBar.high <= box.lower + : iBar.low >= box.upper); + if (!isBreaked) + { + continue; + } + + // + iBar.Clean(); + break; + } + + // + result = isBreaked; + + // + return result; +} + +/** + * Find an Inside Box of source in a Collection ... + * + * @param index: int, Founded Index ... + * @param source: XBoxZone instance ... + * @param dest: XBoxZone instance Collection ... + * + * @return ( bool ) + */ +bool HasInsideBox( + int &index, + XBoxZone &source, + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = source.IsValid() && + HasChild(dest); + + // + int count = ArraySize(dest); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = dest[i]; + + // + bool isInside = !iBox.IsSameAs(source) && + IsBoxInsideOr( + iBox, + source // + ); + if (isInside) + { + // + index = i; + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Remove Specified Box from Collection ... + */ +bool RemoveBox( + XBoxZone &box, + XBoxZone &boxes[] // +) +{ + // + bool result = false; + + // + result = + box.IsValid() && + HasChild(boxes); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindBoxIndex( + idx, + box, + boxes // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + boxes, + idx, + 1 // + ); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCOrderBlock *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = item.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCFVG *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = item.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCSupportZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BULLISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCResistanceZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCSupplyZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCDemandZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BULLISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XConsolidationZone &item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.to; + box.dir = item.dir; + box.from = item.from; + box.upper = item.upper; + box.lower = item.lower; + box.symbol = item.symbol; + box.period = item.period; + box.type = IsBullish(item.dir) + ? ToString(X_BULLISH_CONSOLIDATION_ZONE) + : ToString(X_BEARISH_CONSOLIDATION_ZONE); + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +int ToBox( + XConsolidationZone &source[], + XBoxZone &dest[] // +) +{ + // + int result = 0; + + // + Clean(dest); + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XConsolidationZone iZone = source[i]; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + + // + iBox.Clean(); + iZone.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Get Oldest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetOldest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetYoungest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetHighest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetLowest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +// +// +// + +/** + * Get Oldest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +// +// +// + +// +template +void SortZones( + T *&source[], + ENUM_X_DIRECTION forDir, + bool ignoreInside = true // +) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + has = HasDirection(forDir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(forDir); + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + T *tmpItems[]; + T *last = NULL; + bool hasLast = false; + while (HasChild(source)) + { + // + if (!hasLast) + { + // + idx = GetOldest(source); + hasLast = IsValidIndex(idx); + if (hasLast) + { + // + last = source[idx]; + ArrayRemove( + source, + idx, + 1 // + ); + + // + Add( + last, + tmpItems // + ); + } + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + // + ZeroMemory(last); + break; + } + } + if (!hasLast) + { + // + ZeroMemory(last); + break; + } + + // + T *item = NULL; + idx = GetOldest(source); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(last); + ZeroMemory(item); + break; + } + item = source[idx]; + ArrayRemove( + source, + idx, + 1 // + ); + + // + bool isAbove = IsAbove( + item, + last, + ignoreInside // + ); + + // + bool isBelow = IsBelow( + item, + last, + ignoreInside // + ); + + // + has = + isBullish + ? isAbove + : isBelow; + if (has) + { + // + Add( + item, + tmpItems // + ); + + // + last = item; + hasLast = item != NULL; + } + } + + // + Clean(source); + Copy( + tmpItems, + source // + ); + + // + Clean(tmpItems); +} + +/** + * Extract all Zones Which provided bar is Inside it ... + * + * @return ( int ) + */ +template +int ExtractInsideZones( + XOHCL &bar, // Bar ... + T *&zones[], // Source of Zones ... + T *&dest[] // Dest (all inside Zones) ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int count = ArraySize(zones); + bool isValid = bar.IsValid() && + IsValidSize(count); + if (!isValid) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *iZone = zones[i]; + + // + bool isHighInside = IsInside( + bar.high, + iZone // + ); + + // + bool isLowInside = IsInside( + bar.low, + iZone // + ); + + // + bool isInside = + isLowInside && + isHighInside; + + // + if (isInside) + { + // + Add( + iZone, + dest // + ); + } + + // + ZeroMemory(iZone); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Add Specific Item into a Collection Reference only if it's not Exists ... + * + * @return ( bool ) + */ +template +bool AddIfNotExists( + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + result = item != NULL; + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + Add( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} +bool AddIfNotExists( + XConsolidationZone &item, + XConsolidationZone &items[] // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + AddRef( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} + +/** + * Add items Collection reference Members into source Collection only if it's not Exists ...alignas + * @return ( int ) + */ +template +int AddIfNotExists( + T *&items[], + T *&sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} +int AddIfNotExists( + XConsolidationZone &items[], + XConsolidationZone &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} + +/** + * Update to Time of Specifiex Collection ... + * + * @param items: XOBFVG instance Collection ... + * @param value: datetime ... + */ +template +void SpecifiedUpdateTo( + T *&items[], + datetime value = NULL // +) +{ + // + value = NormalizeTime(value); + + // + int count = ArraySize(items); + bool has = HasChild(items); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + items[i].To(value); + } +} + +// +template +int FilterZones( + // + T *&source[], + // + ENUM_X_DIRECTION forDir, + ENUM_TIMEFRAMES forPeriod = NULL, + datetime after = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false, + // + bool applySort = false, + // + bool ignoreInside = true + // +) +{ + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + has = HasDirection(forDir); + if (!has) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + return result; + } + + // + T *tmpZones[]; + XOHCL passedBar; + bool isPassed = false; + for (int i = 0; i < count; i++) + { + // + T *iZone = source[i]; + + // + // Apply after Filter ... + isPassed = + !IsValid(after) + ? true + : iZone.From() >= after; + if (!isPassed) + { + // + ZeroMemory(iZone); + continue; + } + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + forDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + forDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + forDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + forDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + tmpZones // + ); + if (has) + { + // + ZeroMemory(iZone); + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + tmpZones // + ); + } + + // + Clean(source); + + // + has = HasChild(tmpZones); + if (!has) + { + // + Clean(tmpZones); + passedBar.Clean(); + return result; + } + + // + // Apply Sorting ... + if (applySort) + { + // + T *last = NULL; + bool hasLast = false; + while (HasChild(tmpZones)) + { + // + idx = GetYoungest(tmpZones); + hasLast = IsValidIndex(idx); + if (hasLast) + { + // + last = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + Add( + last, + source // + ); + } + + // + has = HasChild(tmpZones); + if (!has) + { + break; + } + + // + T *zone = NULL; + bool hasZone = false; + idx = GetYoungest(tmpZones); + hasZone = IsValidIndex(idx); + if (hasZone) + { + // + zone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + } + if (!hasZone) + { + // + ZeroMemory(zone); + continue; + } + + // + bool isAbove = IsAbove( + zone, + last, + ignoreInside // + ); + + // + bool isBelow = IsBelow( + zone, + last, + ignoreInside // + ); + + // + isPassed = + isBullish + ? isAbove + : isBelow; + if (!isPassed) + { + // + ZeroMemory(zone); + continue; + } + + // + Add( + zone, + source // + ); + } + } + else + { + // + Copy( + tmpZones, + source // + ); + } + + // + result = ArraySize(source); + + // + return result; +} + +// +// +// + +/** + * Detect Nearest Price Out of Specified Box ... + * + * @param box: XBoxZone instance Reference ... + * @param outSideBar: XOHCL instance Reference which Represents Out Side Bar if Exists ... + * @param forPeriod: ENUM_TIMEFRAMES member which provides time frame of Out Bar, if not Provides used box Period as Default ... + * @param forDir: ENUM_X_DIRECTION member which Specified outSide Direction, use Box Dir as Default ... + * @param forceBodyIn: bool value which Specifyed Body Breakes or not, Default is false ... + * @param barIndex: integer value which Specified Start Bar Index, Default is 0 ... + * + * @return ( bool ) + */ +bool DetectBoxNearestPriceOut( + XBoxZone &box, + XOHCL &outSideBar, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + bool forceBodyIn = false, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + outSideBar.Clean(); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + if (!HasDirection(forDir)) + { + forDir = box.dir; + } + + // + bool isBullish = IsBullish(forDir); + + // + int fromIndex = iBarShift( + box.symbol, + forPeriod, + box.from // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + XOHCL iPBar; + bool has = false; + for (int i = barIndex; i < fromIndex; i++) + { + // + has = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!has) + { + continue; + } + + // + has = iBar.GetPreviousBar(iPBar); + if (!has) + { + continue; + } + + // + bool isInsideFromLower = + iBar.high < box.lower && + iPBar.high > box.lower; + + // + bool isInsideFromUpper = + iBar.low > box.upper && + iPBar.low < box.upper; + + // + bool isInsideBodyFromLower = + iPBar.GetUp() > box.lower; + + // + bool isInsideBodyFromUpper = + iPBar.GetDown() < box.upper; + + // + result = + isBullish + ? (!forceBodyIn + ? isInsideFromLower + : isInsideFromLower && + isInsideBodyFromLower) + : (!forceBodyIn + ? isInsideFromUpper + : isInsideFromUpper && + isInsideBodyFromUpper); + if (result) + { + // + outSideBar = iBar; + break; + } + } + + // + iBar.Clean(); + iPBar.Clean(); + + // + return result; +} + +/** + * Count number of Box Retests ... + * + * @param box: XBoxZone instance Reference ... + * @param forDir: ENUM_X_DIRECTION member, Specified Retesting Direction ... + * @param forPeriod: ENUM_TIMEFRAMES member, Specified Retesting Period ... + * @param forceType: bool, Specified Retest Bar Direction is Same as Retesting Direction ... + * @param forcePressure: bool, Specified Retest Bar must Has Fibo Pressure or not ... + * + * @return ( int ) + */ +int CountBoxRetest( + XBoxZone &box, + ENUM_X_DIRECTION forDir = NULL, + ENUM_TIMEFRAMES forPeriod = NULL, + bool forceType = false, + bool forcePressure = false // +) +{ + // + int result = 0; + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + if (!IsValid(forDir)) + { + forDir = box.dir; + } + + // + bool isValid = + box.IsValid() && + IsValid(forDir); + if (!isValid) + { + return result; + } + + // + int fromIDX = GetBarIndex( + box.symbol, + forPeriod, + box.from // + ); + + // + int toIDX = GetBarIndex( + box.symbol, + forPeriod, + box.to // + ); + + // + for (int i = fromIDX; i >= toIDX; i--) + { + // + // Initialize Indexed Bar ... + XOHCL iBar; + isValid = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!isValid) + { + // + iBar.Clean(); + continue; + } + + // + bool isUpperBullishRejected = iBar.IsRejected( + box.upper, + X_DIRECTION_BULLISH, + forceType, + forcePressure // + ); + bool isUpperBearishRejected = iBar.IsRejected( + box.upper, + X_DIRECTION_BEARISH, + forceType, + forcePressure // + ); + + // + bool isLowerBullishRejected = iBar.IsRejected( + box.lower, + X_DIRECTION_BULLISH, + forceType, + forcePressure // + ); + bool isLowerBearishRejected = iBar.IsRejected( + box.lower, + X_DIRECTION_BEARISH, + forceType, + forcePressure // + ); + + // + if (forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BULLISH) + { + // + if (isUpperBullishRejected || + isLowerBullishRejected) + { + result++; + } + } + + // + if (forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BEARISH) + { + // + if (isUpperBearishRejected || + isLowerBearishRejected) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.state.lib.mq5 b/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.state.lib.mq5 new file mode 100644 index 0000000..e52ea2b --- /dev/null +++ b/BKPS/14040626/Documents/BKP/x-saherelm.x-poi.state.lib.mq5 @@ -0,0 +1,4680 @@ + +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +enum ENUM_X_OBFVG_FVG_FILTERS +{ + X_OBFVG_FVG_FILTER_NONE, + X_OBFVG_FVG_FILTER_INSIDE_OR, + X_OBFVG_FVG_FILTER_ABOVE_BELOW, +}; + +// +enum ENUM_X_OBFVG_FVG_SELECTION +{ + X_OBFVG_FVG_SELECT_NONE, + X_OBFVG_FVG_SELECT_OLDEST, + X_OBFVG_FVG_SELECT_LOWEST, + X_OBFVG_FVG_SELECT_HIGHEST, + X_OBFVG_FVG_SELECT_YOUNGEST, + X_OBFVG_FVG_SELECT_HIGHEST_LOWEST, + X_OBFVG_FVG_SELECT_LOWEST_HIGHEST, +}; + +// +struct XSignalBox +{ + // + XBoxZone ob; + XBoxZone fvg; + XBoxZone sharp; + + // + double sl; + double tp; + + // + // Constructor ... + XSignalBox() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + sl = 0; + tp = 0; + + // + ob.Clean(); + fvg.Clean(); + sharp.Clean(); + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + ob.IsValid() && + fvg.IsValid() && + sharp.IsValid(); + + // + return result; + } + + /** + * Update Structure Models To Date ... + * + * @param value: datetime ... + */ + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + if (ob.IsValid()) + { + ob.to = value; + } + + // + if (fvg.IsValid()) + { + fvg.to = value; + } + + // + if (sharp.IsValid()) + { + sharp.to = value; + } + } + + // +}; + +// +// Model State Parsing ... +struct XPOIStateEvents +{ + // + // Props ... + + // + // Swings ... + bool hasNewSwing; + bool hasNewSwingLow; + bool hasNewSwingHigh; + + // + // Momentums ... + bool hasNewMomentum; + bool hasNewBullishMomentum; + bool hasNewBearishMomentum; + + // + // Rejections ... + bool hasNewRejection; + bool hasNewBullishRejection; + bool hasNewBearishRejection; + + // + // Pullbacks ... + bool hasNewPullback; + bool hasNewBullishPullback; + bool hasNewBearishPullback; + + // + // Support/Resistance (s) ... + bool hasNewSupportZone; + bool hasNewResistanceZone; + + // + // Supply/Demand (s) ... + bool hasNewSupplyZone; + bool hasNewDemandZone; + + // + // Fair Value Gaps ... + bool hasNewFairValueGap; + bool hasNewBullishFairValueGap; + bool hasNewBearishFairValueGap; + + // + // Order Blocks ... + bool hasNewOrderBlock; + bool hasNewBullishOrderBlock; + bool hasNewBearishOrderBlock; + + // + // Spikes ... + bool hasNewSpike; + bool hasNewBullishSpike; + bool hasNewBearishSpike; + + // + // Sharps ... + bool hasNewSharp; + bool hasNewBullishSharp; + bool hasNewBearishSharp; + + // + // Consolidation Zones ... + bool hasNewConsolidationZone; + bool hasNewBullishConsolidationZone; + bool hasNewBearishConsolidationZone; + + // + // Constructor ... + XPOIStateEvents() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + hasNewSwing = false; + hasNewSwingLow = false; + hasNewSwingHigh = false; + + // + hasNewMomentum = false; + hasNewBullishMomentum = false; + hasNewBearishMomentum = false; + + // + hasNewRejection = false; + hasNewBullishRejection = false; + hasNewBearishRejection = false; + + // + hasNewSupportZone = false; + hasNewResistanceZone = false; + + // + hasNewSupplyZone = false; + hasNewDemandZone = false; + + // + hasNewFairValueGap = false; + hasNewBullishFairValueGap = false; + hasNewBearishFairValueGap = false; + + // + hasNewOrderBlock = false; + hasNewBullishOrderBlock = false; + hasNewBearishOrderBlock = false; + + // + hasNewSpike = false; + hasNewBullishSpike = false; + hasNewBearishSpike = false; + + // + hasNewSharp = false; + hasNewBullishSharp = false; + hasNewBearishSharp = false; + + // + hasNewConsolidationZone = false; + hasNewBullishConsolidationZone = false; + hasNewBearishConsolidationZone = false; + + // + ZeroMemory(this); + } + + /** + * Initialize Event Parser Model ... + * + * @param events: ENUM_XPOI_EVENTS members Collection Reference ... + */ + void Init(ENUM_XPOI_EVENTS &events[]) + { + // + hasNewSwing = HasNewSwing(events); + hasNewSwingLow = HasNewSwingLow(events); + hasNewSwingHigh = HasNewSwingHigh(events); + + // + hasNewMomentum = HasNewMomentum(events); + hasNewBullishMomentum = HasNewBullishMomentum(events); + hasNewBearishMomentum = HasNewBearishMomentum(events); + + // + hasNewRejection = HasNewRejection(events); + hasNewBullishRejection = HasNewBullishRejection(events); + hasNewBearishRejection = HasNewBearishRejection(events); + + // + hasNewPullback = HasNewPullback(events); + hasNewBullishPullback = HasNewBullishPullback(events); + hasNewBearishPullback = HasNewBearishPullback(events); + + // + hasNewSupportZone = HasNewSupportZone(events); + hasNewResistanceZone = HasNewResistanceZone(events); + + // + hasNewSupplyZone = HasNewSupplyZone(events); + hasNewDemandZone = HasNewDemandZone(events); + + // + hasNewFairValueGap = HasNewFairValueGap(events); + hasNewBullishFairValueGap = HasNewBullishFairValueGap(events); + hasNewBearishFairValueGap = HasNewBearishFairValueGap(events); + + // + hasNewOrderBlock = HasNewOrderBlock(events); + hasNewBullishOrderBlock = HasNewBullishOrderBlock(events); + hasNewBearishOrderBlock = HasNewBearishOrderBlock(events); + + // + hasNewSpike = HasNewSpike(events); + hasNewBullishSpike = HasNewBullishSpike(events); + hasNewBearishSpike = HasNewBearishSpike(events); + + // + hasNewSharp = HasNewSharp(events); + hasNewBullishSharp = HasNewBullishSharp(events); + hasNewBearishSharp = HasNewBearishSharp(events); + + // + hasNewConsolidationZone = HasNewConsolidationZone(events); + hasNewBullishConsolidationZone = HasNewBullishConsolidationZone(events); + hasNewBearishConsolidationZone = HasNewBearishConsolidationZone(events); + } + + // +}; + +// +// Model Exists Founded POIs ... +struct XPOIState +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XCSwing *swings[]; // Holds Founded Swing ... + XCSwing *swingLows[]; // Holds Founded Swing Lows ... + XCSwing *swingHighs[]; // Holds Founded Swing Highs ... + + // + XCMomentumBar *momentums[]; // Holds Founded Momentum Bars ... + XCMomentumBar *bullishMomentums[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *bearishMomentums[]; // Holds Founded Bearish Momentum Bars ... + + // + XCRejectionBar *rejections[]; // Holds Founded Rejection Bars ... + XCRejectionBar *bullishRejections[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *bearishRejections[]; // Holds Founded Bearish Rejection Bars ... + + // + XCSupportZone *supportZones[]; // Holds Founded Support Zones ... + XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ... + + // + XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ... + XCDemandZone *demandZones[]; // Holds Founded Demand Zones ... + + // + XCOrderBlock *orderBlocks[]; // Holds Founded Order Blocks ... + XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + + // + XCFVG *fairValueGaps[]; // Holds Founded Fair Value Gaps ... + XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + // + XConsolidationZone consolidationZones[]; // Holds Founded Consolidation Zones ... + XConsolidationZone bullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ... + XConsolidationZone bearishConsolidationZones[]; // Holds Founded Bearih Consolidation Zones ... + + // + XBoxZone spikes[]; // Holds Founded Spikes ... + XBoxZone bullishSpikes[]; // Holds Founded Bullish Spikes ... + XBoxZone bearishSpikes[]; // Holds Founded Bearih Spikes ... + + // + XBoxZone sharps[]; // Holds Founded Sharps ... + XBoxZone bullishSharps[]; // Holds Founded Bullish Sharps ... + XBoxZone bearishSharps[]; // Holds Founded Bearih Sharps ... + + // + XBoxZone pullbacks[]; // Holds Founded Pullbacks ... + XBoxZone bullishPullbacks[]; // Holds Founded Bullish Pullbacks ... + XBoxZone bearishPullbacks[]; // Holds Founded Bearish Pullbacks ... + + // + // Constructor ... + void XPOIState() + { + Clean(); + } + + // + // Actions ... + + /** + * Cleanup all props ... + */ + void Clean() + { + // + time = NULL; + symbol = NULL; + period = NULL; + + // + // Swings ... + Clean(swings); + Clean(swingLows); + Clean(swingHighs); + + // + // Momentums ... + Clean(momentums); + Clean(bullishMomentums); + Clean(bearishMomentums); + + // + // Rejections ... + Clean(rejections); + Clean(bullishRejections); + Clean(bearishRejections); + + // + // Support / Resistance Zones ... + Clean(supportZones); + Clean(resistanceZones); + + // + // Supply / Demand Zones ... + Clean(supplyZones); + Clean(demandZones); + + // + // Fair Value Gaps ... + Clean(fairValueGaps); + Clean(bullishFairValueGaps); + Clean(bearishFairValueGaps); + + // + // Order Blocks ... + Clean(orderBlocks); + Clean(bullishOrderBlocks); + Clean(bearishOrderBlocks); + + // + // Spikes ... + Clean(spikes); + Clean(bullishSpikes); + Clean(bearishSpikes); + + // + // Sharps ... + Clean(sharps); + Clean(bullishSharps); + Clean(bearishSharps); + + // + // Pullbaks ... + Clean(pullbacks); + Clean(bullishPullbacks); + Clean(bearishPullbacks); + + // + // Consolidation Zones ... + Clean(consolidationZones); + Clean(bullishConsolidationZones); + Clean(bearishConsolidationZones); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check State has Childs or not ... + * + * @return ( bool ) + */ + bool HasChild() + { + // + bool result = false; + + // + result = + // + // Swings ... + HasSwings() || + HasSwingLows() || + HasSwingHighs() || + // + // Momentums ... + HasMomentums() || + HasBullishMomentums() || + HasBearishMomentums() || + // + // Rejections ... + HasRejections() || + HasBullishRejections() || + HasBearishRejections() || + // + // Pullbacks ... + HasPullbacks() || + HasBullishPullbacks() || + HasBearishPullbacks() || + // + // Support / Resistance Zones ... + HasSupportZones() || + HasResistanceZones() || + // + // Supply / Demand Zones ... + HasSupplyZones() || + HasDemandZones() || + // + // Fair Value Gaps ... + HasFairValueGaps() || + HasBullishFairValueGaps() || + HasBearishFairValueGaps() || + // + // Order Blocks ... + HasOrderBlocks() || + HasBullishOrderBlocks() || + HasBearishOrderBlocks() || + // + // Spikes ... + HasSpikes() || + HasBullishSpikes() || + HasBearishSpikes() || + // + // Sharps ... + HasSharps() || + HasBullishSharps() || + HasBearishSharps() || + // + // Consolidation Zones ... + HasConsolidationZones() || + HasBullishConsolidationZones() || + HasBearishConsolidationZones() + // + ; + + // + return result; + } + + // + // Checkers ... + + // + // Swings ... + + // + // Has ... + + // + bool HasSwings() + { + return HasChild(swings); + } + + // + bool HasSwingLows() + { + return HasChild(swingLows); + } + + // + bool HasSwingHighs() + { + return HasChild(swingHighs); + } + + // + // Count ... + + // + int CountSwings() + { + return ArraySize(swings); + } + + // + int CountSwingLows() + { + return ArraySize(swingLows); + } + + // + int CountSwingHighs() + { + return ArraySize(swingHighs); + } + + // + // Momentums ... + + // + // Has ... + + // + bool HasMomentums() + { + return HasChild(momentums); + } + + // + bool HasBullishMomentums() + { + return HasChild(bullishMomentums); + } + + // + bool HasBearishMomentums() + { + return HasChild(bearishMomentums); + } + + // + // Count ... + + // + int CountMomentums() + { + return ArraySize(momentums); + } + + // + int CountBullishMomentums() + { + return ArraySize(bullishMomentums); + } + + // + int CountBearishMomentums() + { + return ArraySize(bearishMomentums); + } + + // + // Rejections ... + + // + // Has ... + + // + bool HasRejections() + { + return HasChild(rejections); + } + + // + bool HasBullishRejections() + { + return HasChild(bullishRejections); + } + + // + bool HasBearishRejections() + { + return HasChild(bearishRejections); + } + + // + // Count ... + + // + int CountRejections() + { + return ArraySize(rejections); + } + + // + int CountBullishRejections() + { + return ArraySize(bullishRejections); + } + + // + int CountBearishRejections() + { + return ArraySize(bearishRejections); + } + + // + // Pullbacks ... + + // + // Has ... + + // + bool HasPullbacks() + { + return HasChild(pullbacks); + } + + // + bool HasBullishPullbacks() + { + return HasChild(bullishPullbacks); + } + + // + bool HasBearishPullbacks() + { + return HasChild(bearishPullbacks); + } + + // + // Count ... + + // + int CountPullbacks() + { + return ArraySize(pullbacks); + } + + // + int CountBullishPullbacks() + { + return ArraySize(bullishPullbacks); + } + + // + int CountBearishPullbacks() + { + return ArraySize(bearishPullbacks); + } + + // + // Support / Resistance Zones ... + + // + // Has ... + + // + bool HasSupportZones() + { + return HasChild(supportZones); + } + + // + bool HasResistanceZones() + { + return HasChild(resistanceZones); + } + + // + // Count ... + + // + int CountSupportZones() + { + return ArraySize(supportZones); + } + + // + int CountResistanceZones() + { + return ArraySize(resistanceZones); + } + + // + // Supply / Demand Zones ... + + // + // Has ... + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + // Count ... + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + // Fair Value Gaps ... + + // + // Has ... + + // + bool HasFairValueGaps() + { + return HasChild(fairValueGaps); + } + + // + bool HasBullishFairValueGaps() + { + return HasChild(bullishFairValueGaps); + } + + // + bool HasBearishFairValueGaps() + { + return HasChild(bearishFairValueGaps); + } + + // + // Count ... + + // + int CountFairValueGaps() + { + return ArraySize(fairValueGaps); + } + + // + int CountBullishFairValueGaps() + { + return ArraySize(bullishFairValueGaps); + } + + // + int CountBearishFairValueGaps() + { + return ArraySize(bearishFairValueGaps); + } + + // + // Order Blocks ... + + // + // Has ... + + // + bool HasOrderBlocks() + { + return HasChild(orderBlocks); + } + + // + bool HasBullishOrderBlocks() + { + return HasChild(bullishOrderBlocks); + } + + // + bool HasBearishOrderBlocks() + { + return HasChild(bearishOrderBlocks); + } + + // + // Count ... + + // + int CountOrderBlocks() + { + return ArraySize(orderBlocks); + } + + // + int CountBullishOrderBlocks() + { + return ArraySize(bullishOrderBlocks); + } + + // + int CountBearishOrderBlocks() + { + return ArraySize(bearishOrderBlocks); + } + + // + // Spikes ... + + // + // Has ... + + // + bool HasSpikes() + { + return HasChild(spikes); + } + + // + bool HasBullishSpikes() + { + return HasChild(bullishSpikes); + } + + // + bool HasBearishSpikes() + { + return HasChild(bearishSpikes); + } + + // + // Count ... + + // + int CountSpikes() + { + return ArraySize(spikes); + } + + // + int CountBullishSpikes() + { + return ArraySize(bullishSpikes); + } + + // + int CountBearishSpikes() + { + return ArraySize(bearishSpikes); + } + + // + // Sharps ... + + // + // Has ... + + // + bool HasSharps() + { + return HasChild(sharps); + } + + // + bool HasBullishSharps() + { + return HasChild(bullishSharps); + } + + // + bool HasBearishSharps() + { + return HasChild(bearishSharps); + } + + // + // Count ... + + // + int CountSharps() + { + return ArraySize(sharps); + } + + // + int CountBullishSharps() + { + return ArraySize(bullishSharps); + } + + // + int CountBearishSharps() + { + return ArraySize(bearishSharps); + } + + // + // Consolidation Zone ... + + // + // Has ... + + // + bool HasConsolidationZones() + { + return HasChild(consolidationZones); + } + + // + bool HasBullishConsolidationZones() + { + return HasChild(bullishConsolidationZones); + } + + // + bool HasBearishConsolidationZones() + { + return HasChild(bearishConsolidationZones); + } + + // + // Count ... + + // + int CountConsolidationZones() + { + return ArraySize(consolidationZones); + } + + // + int CountBullishConsolidationZones() + { + return ArraySize(bullishConsolidationZones); + } + + // + int CountBearishConsolidationZones() + { + return ArraySize(bearishConsolidationZones); + } + + // + // Box Retrievers ... + + // + int SupportResistancesAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + supportZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + resistanceZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int SupplyDemandsAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + supplyZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + demandZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int OrderBlocksAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + bullishOrderBlocks, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + bearishOrderBlocks, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int FairValueGapsAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + bullishFairValueGaps, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + bearishFairValueGaps, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int SpikesAsBox(XBoxZone &items[]) + { + // + Copy( + bullishSpikes, + items, + false // + ); + + // + Copy( + bearishSpikes, + items, + false // + ); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int SharpsAsBox(XBoxZone &items[]) + { + // + Copy( + bullishSharps, + items, + false // + ); + + // + Copy( + bearishSharps, + items, + false // + ); + + // + int result = ArraySize(items); + + // + return result; + } + + // + // Tools ... + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasMomentums(); + if (has) + { + // + count = CountMomentums(); + for (int i = 0; i < count; i++) + { + momentums[i].To(value); + } + } + + // + has = HasBullishMomentums(); + if (has) + { + // + count = CountBullishMomentums(); + for (int i = 0; i < count; i++) + { + bullishMomentums[i].To(value); + } + } + + // + has = HasBearishMomentums(); + if (has) + { + // + count = CountBearishMomentums(); + for (int i = 0; i < count; i++) + { + bearishMomentums[i].To(value); + } + } + + // + has = HasRejections(); + if (has) + { + // + count = CountRejections(); + for (int i = 0; i < count; i++) + { + rejections[i].To(value); + } + } + + // + has = HasBullishRejections(); + if (has) + { + // + count = CountBullishRejections(); + for (int i = 0; i < count; i++) + { + bullishRejections[i].To(value); + } + } + + // + has = HasBearishRejections(); + if (has) + { + // + count = CountBearishRejections(); + for (int i = 0; i < count; i++) + { + bearishRejections[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasOrderBlocks(); + if (has) + { + // + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + orderBlocks[i].To(value); + } + } + + // + has = HasBullishOrderBlocks(); + if (has) + { + // + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bullishOrderBlocks[i].To(value); + } + } + + // + has = HasBearishOrderBlocks(); + if (has) + { + // + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bearishOrderBlocks[i].To(value); + } + } + + // + has = HasFairValueGaps(); + if (has) + { + // + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + fairValueGaps[i].To(value); + } + } + + // + has = HasBullishFairValueGaps(); + if (has) + { + // + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bullishFairValueGaps[i].To(value); + } + } + + // + has = HasBearishFairValueGaps(); + if (has) + { + // + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bearishFairValueGaps[i].To(value); + } + } + + // + has = HasConsolidationZones(); + if (has) + { + // + count = CountConsolidationZones(); + for (int i = 0; i < count; i++) + { + consolidationZones[i].to = value; + } + } + + // + has = HasBullishConsolidationZones(); + if (has) + { + // + count = CountBullishConsolidationZones(); + for (int i = 0; i < count; i++) + { + bullishConsolidationZones[i].to = value; + } + } + + // + has = HasBearishConsolidationZones(); + if (has) + { + // + count = CountBearishConsolidationZones(); + for (int i = 0; i < count; i++) + { + bearishConsolidationZones[i].to = value; + } + } + + // + has = HasSpikes(); + if (has) + { + // + count = CountSpikes(); + for (int i = 0; i < count; i++) + { + spikes[i].to = value; + } + } + + // + has = HasBullishSpikes(); + if (has) + { + // + count = CountBullishSpikes(); + for (int i = 0; i < count; i++) + { + bullishSpikes[i].to = value; + } + } + + // + has = HasBearishSpikes(); + if (has) + { + // + count = CountBearishSpikes(); + for (int i = 0; i < count; i++) + { + bearishSpikes[i].to = value; + } + } + + // + has = HasSharps(); + if (has) + { + // + count = CountSharps(); + for (int i = 0; i < count; i++) + { + sharps[i].to = value; + } + } + + // + has = HasBullishSharps(); + if (has) + { + // + count = CountBullishSharps(); + for (int i = 0; i < count; i++) + { + bullishSharps[i].to = value; + } + } + + // + has = HasBearishSharps(); + if (has) + { + // + count = CountBearishSharps(); + for (int i = 0; i < count; i++) + { + bearishSharps[i].to = value; + } + } + } + + // + // Filter Zones ... + + // + // Support ... + int FilterSupportZones( + XCSupportZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupportZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = supportZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Resistance ... + int FilterResistanceZones( + XCResistanceZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasResistanceZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = resistanceZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Supply ... + int FilterSupplyZones( + XCSupplyZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupplyZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Demand ... + int FilterDemandZones( + XCDemandZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasDemandZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // OrderBlock ... + int FilterOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = orderBlocks[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish OrderBlock ... + int FilterBullishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bullishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish OrderBlock ... + int FilterBearishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bearishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // FairValueGap ... + int FilterFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = fairValueGaps[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish FairValueGap ... + int FilterBullishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bullishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish FairValueGap ... + int FilterBearishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bearishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + void Filter( + XPOIState &dest, + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int count = 0; + bool has = false; + + // + dest.Clean(); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasChild(); + if (!has) + { + return; + } + + // + dest = this; + + // + // Support Zones ... + FilterSupportZones( + dest.supportZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Resistance Zones ... + FilterResistanceZones( + dest.resistanceZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Supply Zones ... + FilterSupplyZones( + dest.supplyZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Demand Zones ... + FilterDemandZones( + dest.demandZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // OrderBlocks ... + FilterOrderBlocks( + dest.orderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish OrderBlocks ... + FilterBullishOrderBlocks( + dest.bullishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish OrderBlocks ... + FilterBearishOrderBlocks( + dest.bearishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // FairValueGaps ... + FilterFairValueGaps( + dest.fairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish FairValueGaps ... + FilterBullishFairValueGaps( + dest.bullishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish FairValueGaps ... + FilterBearishFairValueGaps( + dest.bearishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + } + + // +}; + +// +// Extensions Functions ... +// + +/** + * Get Oldest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.from > iBox.fvg.from + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.from > iBox.ob.from + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.from > iBox.fvg.from + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.from > iBox.ob.from + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.from < iBox.fvg.from + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.from < iBox.ob.from + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.from < iBox.fvg.from + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.from < iBox.ob.from + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.upper < iBox.fvg.upper + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.upper < iBox.ob.upper + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.upper < iBox.fvg.upper + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.upper < iBox.ob.upper + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.lower > iBox.fvg.lower + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.lower > iBox.ob.lower + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.lower > iBox.fvg.lower + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.lower > iBox.ob.lower + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Find Index of a Signal Box on another ... + * + * @param index: int, index of exists ... + * @param item: XSignal Box ... + * @param items: XSignal Box Collection ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XSignalBox &item, + XSignalBox &items[] // +) +{ + // + bool result = false; + + // + index = -1; + int count = ArraySize(items); + + // + result = item.IsValid() && + HasChild(items); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.ob + .IsSameAs(items[i].ob); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Find Index of a Signal Box on another ... + * + * @param index: int, index of exists ... + * @param item: XSignal Box ... + * @param items: XSignal Box Collection ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XBoxZone &item, + XSignalBox &items[] // +) +{ + // + bool result = false; + + // + index = -1; + int count = ArraySize(items); + + // + result = item.IsValid() && + HasChild(items); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(items[i].ob); + if (isSame) + { + // + index = i; + break; + } + + // + isSame = item.IsSameAs(items[i].fvg); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Add a Signal Box in a Collection if not Exists ... + * + * @param item: XSignal Box ... + * @param items: XSignal Box Collection ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XSignalBox &item, + XSignalBox &items[] // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + result = !FindIndex( + idx, + item, + items // + ); + if (!result) + { + return result; + } + + // + AddRef( + item, + items // + ); + + // + return result; +} + +// +// XPOI State Event Parsers ... + +// +// Swings ... + +// +bool HasNewSwing(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewSwingLow(events) || + HasNewSwingHigh(events); +} + +// +bool HasNewSwingLow(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SWING_LOW_DETECTED, + events // + ); +} + +// +bool HasNewSwingHigh(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SWING_HIGH_DETECTED, + events // + ); +} + +// +// Momentums ... + +// +bool HasNewMomentum(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishMomentum(events) || + HasNewBearishMomentum(events); +} + +// +bool HasNewBullishMomentum(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_MOMENTUM_BAR_DETECTED, + events // + ); +} + +// +bool HasNewBearishMomentum(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_MOMENTUM_BAR_DETECTED, + events // + ); +} + +// +// Rejections ... + +// +bool HasNewRejection(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishRejection(events) || + HasNewBearishRejection(events); +} + +// +bool HasNewBullishRejection(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_REJECTION_BAR_DETECTED, + events // + ); +} + +// +bool HasNewBearishRejection(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_REJECTION_BAR_DETECTED, + events // + ); +} + +// +// Support / Resistance Zones ... + +// +bool HasNewSupportZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SUPPORT_ZONE_DETECTED, + events // + ); +} + +// +bool HasNewResistanceZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_RESISTANCE_ZONE_DETECTED, + events // + ); +} + +// +// Supply / Demand Zones ... + +// +bool HasNewSupplyZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SUPPLY_ZONE_DETECTED, + events // + ); +} + +// +bool HasNewDemandZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_DEMAND_ZONE_DETECTED, + events // + ); +} + +// +// Fair Value Gaps ... + +// +bool HasNewFairValueGap(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishFairValueGap(events) || + HasNewBearishFairValueGap(events); +} + +// +bool HasNewBullishFairValueGap(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_FVG_DETECTED, + events // + ); +} + +// +bool HasNewBearishFairValueGap(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_FVG_DETECTED, + events // + ); +} + +// +// Order Blocks ... + +// +bool HasNewOrderBlock(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishOrderBlock(events) || + HasNewBearishOrderBlock(events); +} + +// +bool HasNewBullishOrderBlock(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + events // + ); +} + +// +bool HasNewBearishOrderBlock(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + events // + ); +} + +// +// Spikes ... + +// +bool HasNewSpike(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishSpike(events) || + HasNewBearishSpike(events); +} + +// +bool HasNewBullishSpike(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_SPIKE_DETECTED, + events // + ); +} + +// +bool HasNewBearishSpike(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_SPIKE_DETECTED, + events // + ); +} + +// +// Sharps ... + +// +bool HasNewSharp(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishSharp(events) || + HasNewBearishSharp(events); +} + +// +bool HasNewBullishSharp(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_SHARP_DETECTED, + events // + ); +} + +// +bool HasNewBearishSharp(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_SHARP_DETECTED, + events // + ); +} + +// +// Pullbacks ... + +// +bool HasNewPullback(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishPullback(events) || + HasNewBearishPullback(events); +} + +// +bool HasNewBullishPullback(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_PULLBACK_DETECTED, + events // + ); +} + +// +bool HasNewBearishPullback(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_PULLBACK_DETECTED, + events // + ); +} + +// +// Consolidation Zones ... + +// +bool HasNewConsolidationZone(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishConsolidationZone(events) || + HasNewBearishConsolidationZone(events); +} + +// +bool HasNewBullishConsolidationZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_CONSOLIDATION_ZONE_DETECTED, + events // + ); +} + +// +bool HasNewBearishConsolidationZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_CONSOLIDATION_ZONE_DETECTED, + events // + ); +} diff --git a/BKPS/14040626/Documents/Diagrams/Position Protection.drawio b/BKPS/14040626/Documents/Diagrams/Position Protection.drawio new file mode 100644 index 0000000..d425cb2 --- /dev/null +++ b/BKPS/14040626/Documents/Diagrams/Position Protection.drawio @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BKPS/14040626/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 new file mode 100644 index 0000000..54cefa5 --- /dev/null +++ b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 @@ -0,0 +1,1556 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121X3MAHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_X3MA_BUFFERS +{ + // + X121_X3MA_FAST = 0, + X121_X3MA_FAST_COLOR = 1, + X121_X3MA_FAST_STATE = 6, + X121_X3MA_MEDIUM = 2, + X121_X3MA_MEDIUM_COLOR = 3, + X121_X3MA_MEDIUM_STATE = 7, + X121_X3MA_SLOW = 4, + X121_X3MA_SLOW_COLOR = 5, + X121_X3MA_SLOW_STATE = 8, +}; + +// +// Input Models ... +struct X121X3MAInputs +{ + // + // Props ... + + // + // FAST ... + int fastLength; + ENUM_MA_METHOD fastMethod; + ENUM_APPLIED_PRICE fastAppliedTo; + + // + // MEDIUM ... + int mediumLength; + ENUM_MA_METHOD mediumMethod; + ENUM_APPLIED_PRICE mediumAppliedTo; + + // + // SLOW ... + int slowLength; + ENUM_MA_METHOD slowMethod; + ENUM_APPLIED_PRICE slowAppliedTo; + + // + // Presentation ... + + // + int startCalculationForLastBars; + + // + bool applyColor; + + // + bool showFast; + bool showSlow; + bool showMedium; + + // + // Constructor ... + X121X3MAInputs() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + // FAST ... + fastLength = 0; + fastMethod = MODE_SMA; + fastAppliedTo = PRICE_CLOSE; + + // + // MEDIUM ... + mediumLength = 0; + mediumMethod = MODE_SMA; + mediumAppliedTo = PRICE_CLOSE; + + // + // SLOW ... + slowLength = 0; + slowMethod = MODE_SMA; + slowAppliedTo = PRICE_CLOSE; + + // + startCalculationForLastBars = 0; + + // + applyColor = false; + + // + showFast = false; + showSlow = false; + showMedium = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // FAST ... + fastLength = 6; + fastMethod = MODE_SMA; + fastAppliedTo = PRICE_CLOSE; + + // + // MEDIUM ... + mediumLength = 21; + mediumMethod = MODE_SMA; + mediumAppliedTo = PRICE_CLOSE; + + // + // SLOW ... + slowLength = 34; + slowMethod = MODE_SMA; + slowAppliedTo = PRICE_CLOSE; + + // + startCalculationForLastBars = 1000; + + // + applyColor = true; + + // + showFast = true; + showSlow = true; + showMedium = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showFast = false; + showSlow = false; + showMedium = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + fastLength > 2 && + mediumLength > 2 && + slowLength > 2 && + mediumLength > fastLength && + mediumLength < slowLength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(fastLength, mediumLength); + result = MathMax(result, slowLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121X3MAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + double fastBuffer[]; + double mediumBuffer[]; + double slowBuffer[]; + double fastStateBuffer[]; + double mediumStateBuffer[]; + double slowStateBuffer[]; + + // + // Conditions ... + + // + bool isFastOverMedium; + bool isFastUnderMedium; + + // + bool isFastCrossedOverMedium; + bool isFastCrossedUnderMedium; + + // + bool isFastOverSlow; + bool isFastUnderSlow; + + // + bool isFastCrossedOverSlow; + bool isFastCrossedUnderSlow; + + // + bool isMediumOverSlow; + bool isMediumUnderSlow; + + // + bool isMediumCrossedOverSlow; + bool isMediumCrossedUnderSlow; + + // + bool is3MaBullishOrdered; + bool is3MaBearishOrdered; + + // + bool is3MaSwitchedToBullishOrdered; + bool is3MaSwitchedToBearishOrdered; + + // + bool is3MaBullishState; + bool is3MaBearishState; + + // + bool is3MaSwitchedToBullishState; + bool is3MaSwitchedToBearishState; + + // + bool is3MaBullish; + bool is3MaBearish; + + // + bool is3MaSwitchedToBullish; + bool is3MaSwitchedToBearish; + + // + bool is3MaFinishedFromBullish; + bool is3MaFinishedFromBearish; + + // + // Constructor ... + X121X3MAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(fastBuffer); + Clean(mediumBuffer); + Clean(slowBuffer); + Clean(fastStateBuffer); + Clean(mediumStateBuffer); + Clean(slowStateBuffer); + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(mediumBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(fastStateBuffer, true); + ArraySetAsSeries(mediumStateBuffer, true); + ArraySetAsSeries(slowStateBuffer, true); + + // + // Conditions ... + + // + isFastOverMedium = false; + isFastUnderMedium = false; + + // + isFastCrossedOverMedium = false; + isFastCrossedUnderMedium = false; + + // + isFastOverSlow = false; + isFastUnderSlow = false; + + // + isFastCrossedOverSlow = false; + isFastCrossedUnderSlow = false; + + // + isMediumOverSlow = false; + isMediumUnderSlow = false; + + // + isMediumCrossedOverSlow = false; + isMediumCrossedUnderSlow = false; + + // + is3MaBullishOrdered = false; + is3MaBearishOrdered = false; + + // + is3MaSwitchedToBullishOrdered = false; + is3MaSwitchedToBearishOrdered = false; + + // + is3MaBullishState = false; + is3MaBearishState = false; + + // + is3MaSwitchedToBullishState = false; + is3MaSwitchedToBearishState = false; + + // + is3MaBullish = false; + is3MaBearish = false; + + // + is3MaSwitchedToBullish = false; + is3MaSwitchedToBearish = false; + + // + is3MaFinishedFromBullish = false; + is3MaFinishedFromBearish = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + if (isFastOverSlow) + { + bullishScore += minScore; + } + if (isFastOverMedium) + { + bullishScore += minScore; + } + if (isMediumOverSlow) + { + bullishScore += minScore; + } + if (isFastCrossedOverSlow) + { + bullishScore += score; + } + if (isFastCrossedOverMedium) + { + bullishScore += score; + } + if (isMediumCrossedOverSlow) + { + bullishScore += score; + } + + // + if (is3MaBullish) + { + bullishScore += minScore; + } + if (is3MaBullishState) + { + bullishScore += minScore; + } + if (is3MaBullishOrdered) + { + bullishScore += minScore; + } + if (is3MaSwitchedToBullish) + { + bullishScore += minScore; + } + if (is3MaFinishedFromBearish) + { + bullishScore += minScore; + } + if (is3MaSwitchedToBullishState) + { + bullishScore += minScore; + } + if (is3MaSwitchedToBullishOrdered) + { + bullishScore += minScore; + } + + // + if (isFastUnderSlow) + { + bearishScore += minScore; + } + if (isMediumUnderSlow) + { + bearishScore += minScore; + } + if (isFastUnderMedium) + { + bearishScore += minScore; + } + if (isFastCrossedUnderSlow) + { + bearishScore += score; + } + if (isFastCrossedUnderMedium) + { + bearishScore += score; + } + if (isMediumCrossedUnderSlow) + { + bearishScore += score; + } + + // + if (is3MaBearish) + { + bearishScore += minScore; + } + if (is3MaBearishState) + { + bearishScore += minScore; + } + if (is3MaBearishOrdered) + { + bearishScore += minScore; + } + if (is3MaSwitchedToBearish) + { + bearishScore += minScore; + } + if (is3MaFinishedFromBullish) + { + bearishScore += minScore; + } + if (is3MaSwitchedToBearishState) + { + bearishScore += minScore; + } + if (is3MaSwitchedToBearishOrdered) + { + bearishScore += minScore; + } + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "X3MA: " + separator + + "-----------------------" + separator + + ToString("isFastOverMedium", isFastOverMedium, ignoreFalseConditions, separator) + + ToString("isFastUnderMedium", isFastUnderMedium, ignoreFalseConditions, separator) + + ToString("isFastCrossedOverMedium", isFastCrossedOverMedium, ignoreFalseConditions, separator) + + ToString("isFastCrossedUnderMedium", isFastCrossedUnderMedium, ignoreFalseConditions, separator) + + ToString("isFastOverSlow", isFastOverSlow, ignoreFalseConditions, separator) + + ToString("isFastUnderSlow", isFastUnderSlow, ignoreFalseConditions, separator) + + ToString("isFastCrossedOverSlow", isFastCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isFastCrossedUnderSlow", isFastCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("isMediumOverSlow", isMediumOverSlow, ignoreFalseConditions, separator) + + ToString("isMediumUnderSlow", isMediumUnderSlow, ignoreFalseConditions, separator) + + ToString("isMediumCrossedOverSlow", isMediumCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isMediumCrossedUnderSlow", isMediumCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("is3MaBullishOrdered", is3MaBullishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaBearishOrdered", is3MaBearishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBullishOrdered", is3MaSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBearishOrdered", is3MaSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaBullishState", is3MaBullishState, ignoreFalseConditions, separator) + + ToString("is3MaBearishState", is3MaBearishState, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBullishState", is3MaSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBearishState", is3MaSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("is3MaBullish", is3MaBullish, ignoreFalseConditions, separator) + + ToString("is3MaBearish", is3MaBearish, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBullish", is3MaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBearish", is3MaSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("is3MaFinishedFromBullish", is3MaFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("is3MaFinishedFromBearish", is3MaFinishedFromBearish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121X3MAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121X3MAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121X3MAHelper() + { + // + mInputs.Clean(); + + // + Clean(fastBuffer); + Clean(mediumBuffer); + Clean(slowBuffer); + Clean(fastStateBuffer); + Clean(mediumStateBuffer); + Clean(slowStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121X3MAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(mediumBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(fastStateBuffer, true); + ArraySetAsSeries(mediumStateBuffer, true); + ArraySetAsSeries(slowStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.x3ma", + "", // FAST ... + mInputs.fastLength, + mInputs.fastMethod, + mInputs.fastAppliedTo, + "", // MEDIUM ... + mInputs.mediumLength, + mInputs.mediumMethod, + mInputs.mediumAppliedTo, + "", // SLOW ... + mInputs.slowLength, + mInputs.slowMethod, + mInputs.slowAppliedTo, + "", // Presentation ... + mInputs.startCalculationForLastBars, + mInputs.applyColor, + mInputs.showFast, + mInputs.showSlow, + mInputs.showMedium + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121X3MAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121X3MAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // FAST ... + + // + double GetFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastBuffer[barIndex]; + } + + // + int CopyFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fastBuffer, + buffer, + forceClean + // + ); + } + + // + // FAST STATE ... + + // + double GetFastState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fastStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastStateBuffer[barIndex]; + } + + // + int CopyFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fastStateBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + double GetMedium( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mediumBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mediumBuffer[barIndex]; + } + + // + int CopyMedium( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mediumBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM STATE ... + + // + double GetMediumState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mediumStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mediumStateBuffer[barIndex]; + } + + // + int CopyMediumState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mediumStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SLOW ... + + // + double GetSlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(slowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowBuffer[barIndex]; + } + + // + int CopySlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + slowBuffer, + buffer, + forceClean + // + ); + } + + // + // SLOW STATE ... + + // + double GetSlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(slowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowStateBuffer[barIndex]; + } + + // + int CopySlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + slowStateBuffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + // FAST ... + + // + CopyFast( + zIndex, + loopback, + conditions.fastBuffer // + ); + + // + CopyFastState( + zIndex, + loopback, + conditions.fastStateBuffer // + ); + + // + // MEDIUM ... + + // + CopyMedium( + zIndex, + loopback, + conditions.mediumBuffer // + ); + + // + CopyMediumState( + zIndex, + loopback, + conditions.mediumStateBuffer // + ); + + // + // SLOW ... + + // + CopySlow( + zIndex, + loopback, + conditions.slowBuffer // + ); + + // + CopySlowState( + zIndex, + loopback, + conditions.slowStateBuffer // + ); + + // + // Conditions ... + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Calculate ... + + // + // FAST ... + + // + double cFast = conditions.fastBuffer[cIDX]; + double pFast = conditions.fastBuffer[pIDX]; + double p2Fast = conditions.fastBuffer[p2IDX]; + + // + double cFastState = conditions.fastStateBuffer[cIDX]; + double pFastState = conditions.fastStateBuffer[pIDX]; + double p2FastState = conditions.fastStateBuffer[p2IDX]; + + // + // MEDIUM ... + + // + double cMedium = conditions.mediumBuffer[cIDX]; + double pMedium = conditions.mediumBuffer[pIDX]; + double p2Medium = conditions.mediumBuffer[p2IDX]; + + // + double cMediumState = conditions.mediumStateBuffer[cIDX]; + double pMediumState = conditions.mediumStateBuffer[pIDX]; + double p2MediumState = conditions.mediumStateBuffer[p2IDX]; + + // + // FAST ... + + // + double cSlow = conditions.slowBuffer[cIDX]; + double pSlow = conditions.slowBuffer[pIDX]; + double p2Slow = conditions.slowBuffer[p2IDX]; + + // + double cSlowState = conditions.slowStateBuffer[cIDX]; + double pSlowState = conditions.slowStateBuffer[pIDX]; + double p2SlowState = conditions.slowStateBuffer[p2IDX]; + + // + // Conditions ... + + // + bool isFastOverMedium = cFast > cMedium; + bool isFastOverMediumPrev = pFast > pMedium; + bool isFastCrossedOverMedium = isFastOverMedium && + !isFastOverMediumPrev; + + // + bool isFastUnderMedium = cFast < cMedium; + bool isFastUnderMediumPrev = pFast < pMedium; + bool isFastCrossedUnderMedium = isFastUnderMedium && + !isFastUnderMediumPrev; + + // + bool isFastOverSlow = cFast > cSlow; + bool isFastOverSlowPrev = pFast > pSlow; + bool isFastCrossedOverSlow = isFastOverSlow && + !isFastOverSlowPrev; + + // + bool isFastUnderSlow = cFast < cSlow; + bool isFastUnderSlowPrev = pFast < pSlow; + bool isFastCrossedUnderSlow = isFastUnderSlow && + !isFastUnderSlowPrev; + + // + bool isMediumOverSlow = cMedium > cSlow; + bool isMediumOverSlowPrev = pMedium > pSlow; + bool isMediumCrossedOverSlow = isMediumOverSlow && + !isMediumOverSlowPrev; + + // + bool isMediumUnderSlow = cMedium < cSlow; + bool isMediumUnderSlowPrev = pMedium < pSlow; + bool isMediumCrossedUnderSlow = isMediumUnderSlow && + !isMediumUnderSlowPrev; + + // + bool is3MaBullishOrdered = + isFastOverMedium && + isMediumOverSlow; + bool is3MaBullishOrderedPrev = + isFastOverMediumPrev && + isMediumOverSlowPrev; + + // + bool is3MaBearishOrdered = + isFastUnderMedium && + isMediumUnderSlow; + bool is3MaBearishOrderedPrev = + isFastUnderMediumPrev && + isMediumUnderSlowPrev; + + // + bool is3MaSwitchedToBullishOrdered = is3MaBullishOrdered && + !is3MaBullishOrderedPrev; + bool is3MaSwitchedToBearishOrdered = is3MaBearishOrdered && + !is3MaBearishOrderedPrev; + + // + bool is3MaBullishState = + cFastState > 0 && + cMediumState > 0 && + cSlowState > 0; + bool is3MaBullishStatePrev = + pFastState > 0 && + pMediumState > 0 && + pSlowState > 0; + + // + bool is3MaBearishState = + cFastState < 0 && + cMediumState < 0 && + cSlowState < 0; + bool is3MaBearishStatePrev = + pFastState < 0 && + pMediumState < 0 && + pSlowState < 0; + + // + bool is3MaSwitchedToBullishState = is3MaBullishState && + !is3MaBullishStatePrev; + bool is3MaSwitchedToBearishState = is3MaBearishState && + !is3MaBearishStatePrev; + + // + bool is3MaBullish = + is3MaBullishState && + is3MaBullishOrdered; + bool is3MaBullishPrev = + is3MaBullishStatePrev && + is3MaBullishOrderedPrev; + + // + bool is3MaBearish = + is3MaBearishState && + is3MaBearishOrdered; + bool is3MaBearishPrev = + is3MaBearishStatePrev && + is3MaBearishOrderedPrev; + + // + bool is3MaSwitchedToBullish = is3MaBullish && + !is3MaBullishPrev; + bool is3MaSwitchedToBearish = is3MaBearish && + !is3MaBearishPrev; + + // + bool is3MaFinishedFromBullish = !is3MaBullish && + is3MaBullishPrev; + bool is3MaFinishedFromBearish = !is3MaBearish && + is3MaBearishPrev; + + // + conditions.is3MaBullish = is3MaBullish; + conditions.is3MaBearish = is3MaBearish; + conditions.isFastOverSlow = isFastOverSlow; + conditions.isFastUnderSlow = isFastUnderSlow; + conditions.isFastOverMedium = isFastOverMedium; + conditions.isMediumOverSlow = isMediumOverSlow; + conditions.isFastUnderMedium = isFastUnderMedium; + conditions.isMediumUnderSlow = isMediumUnderSlow; + conditions.is3MaBullishState = is3MaBullishState; + conditions.is3MaBearishState = is3MaBearishState; + conditions.is3MaBullishOrdered = is3MaBullishOrdered; + conditions.is3MaBearishOrdered = is3MaBearishOrdered; + conditions.isFastCrossedOverSlow = isFastCrossedOverSlow; + conditions.is3MaSwitchedToBullish = is3MaSwitchedToBullish; + conditions.is3MaSwitchedToBearish = is3MaSwitchedToBearish; + conditions.isFastCrossedUnderSlow = isFastCrossedUnderSlow; + conditions.isFastCrossedOverMedium = isFastCrossedOverMedium; + conditions.isMediumCrossedOverSlow = isMediumCrossedOverSlow; + conditions.is3MaFinishedFromBullish = is3MaFinishedFromBullish; + conditions.is3MaFinishedFromBearish = is3MaFinishedFromBearish; + conditions.isFastCrossedUnderMedium = isFastCrossedUnderMedium; + conditions.isMediumCrossedUnderSlow = isMediumCrossedUnderSlow; + conditions.is3MaSwitchedToBullishState = is3MaSwitchedToBullishState; + conditions.is3MaSwitchedToBearishState = is3MaSwitchedToBearishState; + conditions.is3MaSwitchedToBullishOrdered = is3MaSwitchedToBullishOrdered; + conditions.is3MaSwitchedToBearishOrdered = is3MaSwitchedToBearishOrdered; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121X3MAInputs mInputs; // Inputs ... + + // + // Buffers ... + double fastBuffer[]; + double mediumBuffer[]; + double slowBuffer[]; + double fastStateBuffer[]; + double mediumStateBuffer[]; + double slowStateBuffer[]; + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // FAST ... + + // + CopyBuffer( + mHandler, + X121_X3MA_FAST, + barIndex, + maxRequiredBars, + fastBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_X3MA_FAST_STATE, + barIndex, + maxRequiredBars, + fastStateBuffer // + ); + + // + // MEDIUM ... + + // + CopyBuffer( + mHandler, + X121_X3MA_MEDIUM, + barIndex, + maxRequiredBars, + mediumBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_X3MA_MEDIUM_STATE, + barIndex, + maxRequiredBars, + mediumStateBuffer // + ); + + // + // SLOW ... + + // + CopyBuffer( + mHandler, + X121_X3MA_SLOW, + barIndex, + maxRequiredBars, + slowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_X3MA_SLOW_STATE, + barIndex, + maxRequiredBars, + slowStateBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + fastBuffer, + maxAllowed // + ); + + // + CleanupArray( + mediumBuffer, + maxAllowed // + ); + + // + CleanupArray( + slowBuffer, + maxAllowed // + ); + + // + CleanupArray( + fastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + mediumStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + slowStateBuffer, + maxAllowed // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 new file mode 100644 index 0000000..f7f1edb --- /dev/null +++ b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 @@ -0,0 +1,5275 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCAHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_XCA_BUFFERS +{ + // + X121_XCA_S_HH_LINE = 0, + X121_XCA_S_LL_LINE = 1, + X121_XCA_M_HH_LINE = 2, + X121_XCA_M_LL_LINE = 3, + X121_XCA_L_HH_LINE = 4, + X121_XCA_L_LL_LINE = 5, + X121_XCA_H_HH_LINE = 6, + X121_XCA_H_LL_LINE = 7, + X121_XCA_SUPPORT_LINE = 8, + X121_XCA_RESISTANCE_LINE = 9, + X121_XCA_PEAK_LINE = 10, + X121_XCA_PEAK_GOLDEN_LINE = 11, + X121_XCA_VALE_LINE = 12, + X121_XCA_VALE_GOLDEN_LINE = 13, + X121_XCA_FIBO_L1_LINE = 14, + X121_XCA_FIBO_L2_LINE = 15, + X121_XCA_FIBO_L3_LINE = 16, + X121_XCA_FIBO_L4_LINE = 17, + X121_XCA_FIBO_L5_LINE = 18, + X121_XCA_SAR_LINE = 19, + X121_XCA_TREND_LINE = 20, + X121_XCA_KI_LINE = 22, + X121_XCA_SWING_LOW_LINE = 24, + X121_XCA_SWING_HIGH_LINE = 25, + X121_XCA_TKI_LINE = 26, + X121_XCA_VIDYA_LINE = 28, + X121_XCA_MAH_LINE = 30, + X121_XCA_MAL_LINE = 31, + X121_XCA_MAC_LINE = 32, + X121_XCA_TREND_STATE_LINE = 33, + X121_XCA_KI_STATE_LINE = 34, + X121_XCA_TKI_STATE_LINE = 35, + X121_XCA_VIDYA_STATE_LINE = 36, +}; + +// +// Input Models ... +struct X121XCAInputs +{ + // + // Props ... + + // + // Market ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Boundary Detection ... + ENUM_SERIESMODE hhMode; // Highest High Calculation Method + ENUM_SERIESMODE llMode; // Lowest Low Calculation Method + ENUM_X_FIBO_LEVELS goldenZoneLevel; // Golden Zone Detection + + // + // Fibo Levels ... + ENUM_X_FIBO_LEVELS fiboLevel1; // Fibo Level 1 + ENUM_X_FIBO_LEVELS fiboLevel2; // Fibo Level 2 + ENUM_X_FIBO_LEVELS fiboLevel3; // Fibo Level 3 + ENUM_X_FIBO_LEVELS fiboLevel4; // Fibo Level 4 + ENUM_X_FIBO_LEVELS fiboLevel5; // Fibo Level 5 + + // + // Sar Detection ... + double sarStep; // Step + double sarMax; // Maximum + + // + // KI ... + int kiLength; // KI Length + + // + // VIDYA ... + int vidyaCMOLength; // CMO (Candle Momentum) Length + int vidyaEMALength; // EMA Length + ENUM_APPLIED_PRICE vidyaAppliedTo; // Applied To + + // + // MANALYSER ... + int manalyserLength; // Length + ENUM_MA_METHOD manalyserMethod; // Method + + // + // Swing Detection ... + int swingLength; // Length + + // + // Support and Resistance ... + int supResSmoothingLength; // Smoothing Length + ENUM_X_MA_METHOD supResSmoothingMode; // Smoothing Method + + // + // Presentation ... + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + bool showSar; // Show Sar + bool showKI; // Show KI + bool showTKI; // Show TKI + bool showMAH; // Show MAH + bool showMAL; // Show MAL + bool showMAC; // Show MAC + bool showVidya; // Show Vidya + bool showTrend; // Show Trend + bool showSwings; // Show Swings + bool showFiboLevel1; // Show Fibo Level 1 + bool showFiboLevel2; // Show Fibo Level 2 + bool showFiboLevel3; // Show Fibo Level 3 + bool showFiboLevel4; // Show Fibo Level 4 + bool showFiboLevel5; // Show Fibo Level 5 + bool showPeaksAndVales; // Show Peaks And Vales + bool showPeakAndValeGolden; // Show Peak and Vale Golden + bool showSupportAndResistance; // Show Support and Resistance + + // + bool showShortCycle; // Show Short Cycle + bool showMediumCycle; // Show Medium Cycle + bool showLongCycle; // Show Long Cycle + bool showHindCycle; // Show Hind Cycle + + // + int sarArrowCode; // Parabolic Sar Arrow Code + int peakArrowCode; // Peaks Arrow Code + int valeArrowCode; // Vales Arrow Code + int swingLowArrowCode; // Swing Low Arrow Code + int swingHighArrowCode; // Swing High Arrow Code + + // + // Constructor(s) ... + X121XCAInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; // How to Find Period + scPeriod = NULL; // Time Period + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; // How to Find Period + mcPeriod = NULL; // Time Period + + // + // Long ... + lcMethod = X_PERIOD_AUTO; // How to Find Period + lcPeriod = NULL; // Time Period + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; // How to Find Period + hcPeriod = NULL; // Time Period + + // + // Boundary Detection ... + hhMode = MODE_HIGH; // Highest High Calculation Method + llMode = MODE_LOW; // Lowest Low Calculation Method + + // + // Fibo Levels ... + fiboLevel1 = X_FIBO_LEVEL_236; // Fibo Level 1 + fiboLevel2 = X_FIBO_LEVEL_382; // Fibo Level 2 + fiboLevel3 = X_FIBO_LEVEL_500; // Fibo Level 3 + fiboLevel4 = X_FIBO_LEVEL_618; // Fibo Level 4 + fiboLevel5 = X_FIBO_LEVEL_764; // Fibo Level 5 + + // + // Sar Detection ... + sarStep = 0; // Step + sarMax = 0; // Maximum + + // + // KI ... + kiLength = 0; // KI Length + + // + // VIDYA ... + vidyaCMOLength = 0; + vidyaEMALength = 0; + vidyaAppliedTo = PRICE_CLOSE; + + // + // MANALYSER ... + manalyserLength = 0; // Length + manalyserMethod = MODE_SMA; // Method + + // + // Swing Detection ... + swingLength = 0; // Length + + // + // Support and Resistance ... + supResSmoothingLength = 0; // Smoothing Length + supResSmoothingMode = X_MA_MODE_NONE; // Smoothing Method + + // + // Presentation ... + + // + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + showSar = false; // Show Sar + showKI = false; // Show KI + showTKI = false; // Show TKI + showMAH = false; // Show MAH + showMAL = false; // Show MAL + showMAC = false; // Show MAC + showVidya = false; // Show Vidya + showTrend = false; // Show Trend + showSwings = false; // Show Swings + showFiboLevel1 = false; // Show Fibo Level 1 + showFiboLevel2 = false; // Show Fibo Level 2 + showFiboLevel3 = false; // Show Fibo Level 3 + showFiboLevel4 = false; // Show Fibo Level 4 + showFiboLevel5 = false; // Show Fibo Level 5 + showPeaksAndVales = false; // Show Peaks And Vales + showPeakAndValeGolden = false; // Show Peak and Vale Golden + showSupportAndResistance = false; // Show Support and Resistance + + // + showShortCycle = false; // Show Short Cycle + showMediumCycle = false; // Show Medium Cycle + showLongCycle = false; // Show Long Cycle + showHindCycle = false; // Show Hind Cycle + + // + sarArrowCode = 0; // Parabolic Sar Arrow Code + peakArrowCode = 0; // Peaks Arrow Code + valeArrowCode = 0; // Vales Arrow Code + swingLowArrowCode = 0; // Swing Low Arrow Code + swingHighArrowCode = 0; // Swing High Arrow Code + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Market ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; // How to Find Period + scPeriod = NULL; // Time Period + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; // How to Find Period + mcPeriod = NULL; // Time Period + + // + // Long ... + lcMethod = X_PERIOD_AUTO; // How to Find Period + lcPeriod = NULL; // Time Period + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; // How to Find Period + hcPeriod = NULL; // Time Period + + // + // Boundary Detection ... + hhMode = MODE_HIGH; // Highest High Calculation Method + llMode = MODE_LOW; // Lowest Low Calculation Method + + // + // Fibo Levels ... + fiboLevel1 = X_FIBO_LEVEL_236; // Fibo Level 1 + fiboLevel2 = X_FIBO_LEVEL_382; // Fibo Level 2 + fiboLevel3 = X_FIBO_LEVEL_500; // Fibo Level 3 + fiboLevel4 = X_FIBO_LEVEL_618; // Fibo Level 4 + fiboLevel5 = X_FIBO_LEVEL_764; // Fibo Level 5 + + // + // Sar Detection ... + sarStep = 0.02; // Step + sarMax = 0.2; // Maximum + + // + // KI ... + kiLength = 26; // KI Length + + // + // VIDYA ... + vidyaCMOLength = 20; + vidyaEMALength = 14; + vidyaAppliedTo = PRICE_CLOSE; + + // + // MANALYSER ... + manalyserLength = 14; // Length + manalyserMethod = MODE_SMA; // Method + + // + // Swing Detection ... + swingLength = 5; // Length + + // + // Presentation ... + + // + startCalculationForLastBars = 1000; // Calculate Last n Bars + + // + showSar = true; // Show Sar + showKI = true; // Show KI + showTKI = true; // Show TKI + showMAH = true; // Show MAH + showMAL = true; // Show MAL + showMAC = true; // Show MAC + showVidya = true; // Show Vidya + showTrend = true; // Show Trend + showSwings = true; // Show Swings + showFiboLevel1 = true; // Show Fibo Level 1 + showFiboLevel2 = true; // Show Fibo Level 2 + showFiboLevel3 = true; // Show Fibo Level 3 + showFiboLevel4 = true; // Show Fibo Level 4 + showFiboLevel5 = true; // Show Fibo Level 5 + showPeaksAndVales = true; // Show Peaks And Vales + showPeakAndValeGolden = true; // Show Peak and Vale Golden + showSupportAndResistance = true; // Show Support and Resistance + + // + showShortCycle = true; // Show Short Cycle + showMediumCycle = true; // Show Medium Cycle + showLongCycle = true; // Show Long Cycle + showHindCycle = true; // Show Hind Cycle + + // + sarArrowCode = 159; // Parabolic Sar Arrow Code + peakArrowCode = 159; // Peaks Arrow Code + valeArrowCode = 159; // Vales Arrow Code + swingLowArrowCode = 225; // Swing Low Arrow Code + swingHighArrowCode = 226; // Swing High Arrow Code + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showSar = false; // Show Sar + showKI = false; // Show KI + showTKI = false; // Show TKI + showMAH = false; // Show MAH + showMAL = false; // Show MAL + showMAC = false; // Show MAC + showVidya = false; // Show Vidya + showTrend = false; // Show Trend + showSwings = false; // Show Swings + showFiboLevel1 = false; // Show Fibo Level 1 + showFiboLevel2 = false; // Show Fibo Level 2 + showFiboLevel3 = false; // Show Fibo Level 3 + showFiboLevel4 = false; // Show Fibo Level 4 + showFiboLevel5 = false; // Show Fibo Level 5 + showPeaksAndVales = false; // Show Peaks And Vales + showPeakAndValeGolden = false; // Show Peak and Vale Golden + showSupportAndResistance = false; // Show Support and Resistance + + // + showShortCycle = false; // Show Short Cycle + showMediumCycle = false; // Show Medium Cycle + showLongCycle = false; // Show Long Cycle + showHindCycle = false; // Show Hind Cycle + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + kiLength > 0 && + swingLength > 0 && + sarMax > sarStep && + vidyaCMOLength > 0 && + vidyaEMALength > 0 && + manalyserLength > 0 && + // + // XCA ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(kiLength, swingLength); + result = MathMax(result, vidyaCMOLength); + result = MathMax(result, vidyaEMALength); + result = MathMax(result, manalyserLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XCAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double kiBuffer[]; + double tkiBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double sarBuffer[]; + double mahBuffer[]; + double malBuffer[]; + double macBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double vidyaBuffer[]; + double trendBuffer[]; + double kiStateBuffer[]; + double supportBuffer[]; + double tkiStateBuffer[]; + double swingLowBuffer[]; + double swingHighBuffer[]; + double vidyaStateBuffer[]; + double resistanceBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double fiboLevel1Buffer[]; + double fiboLevel2Buffer[]; + double fiboLevel3Buffer[]; + double fiboLevel4Buffer[]; + double fiboLevel5Buffer[]; + double trendStateBuffer[]; + + // + // Conditions ... + + // + // KI ... + + // + bool isKIRejectUp; + bool isKIRejectDown; + + // + bool isKIBullish; + bool isKIBearish; + + // + bool isKISwitchedToBullish; + bool isKISwitchedToBearish; + + // + bool isKIFinishedFromBullish; + bool isKIFinishedFromBearish; + + // + // TKI ... + + // + bool isTKIRejectUp; + bool isTKIRejectDown; + + // + bool isTKIBullish; + bool isTKIBearish; + + // + bool isTKISwitchedToBullish; + bool isTKISwitchedToBearish; + + // + bool isTKIFinishedFromBullish; + bool isTKIFinishedFromBearish; + + // + // VIDYA ... + + // + bool isVidyaRejectUp; + bool isVidyaRejectDown; + + // + bool isVidyaBullish; + bool isVidyaBearish; + + // + bool isVidyaSwitchedToBullish; + bool isVidyaSwitchedToBearish; + + // + bool isVidyaFinishedFromBullish; + bool isVidyaFinishedFromBearish; + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + bool isSarFinishedFromBullish; + bool isSarFinishedFromBearish; + + // + // MANALYSER ... + + // + // MAH ... + + // + bool isOverMah; + bool isUnderMah; + bool isCrossedOverMah; + bool isCrossedUnderMah; + + // + bool isCloseOverMah; + bool isCloseUnderMah; + bool isCloseCrossedOverMah; + bool isCloseCrossedUnderMah; + + // + bool isMahBullishRejected; + bool isMahBearishRejected; + + // + // MAL ... + + // + bool isOverMal; + bool isUnderMal; + bool isCrossedOverMal; + bool isCrossedUnderMal; + + // + bool isCloseOverMal; + bool isCloseUnderMal; + bool isCloseCrossedOverMal; + bool isCloseCrossedUnderMal; + + // + bool isMalBullishRejected; + bool isMalBearishRejected; + + // + // MAC ... + + // + bool isOverMac; + bool isUnderMac; + bool isCrossedOverMac; + bool isCrossedUnderMac; + + // + bool isCloseOverMac; + bool isCloseUnderMac; + bool isCloseCrossedOverMac; + bool isCloseCrossedUnderMac; + + // + bool isMacBullishRejected; + bool isMacBearishRejected; + + // + // PEAK ... + + // + bool isPeakSameLast; + bool isPeakOverLast; + bool isPeakUnderLast; + + // + // VALE ... + + // + bool isValeSameLast; + bool isValeOverLast; + bool isValeUnderLast; + + // + // TREND ... + + // + bool isTrendRejectUp; + bool isTrendRejectDown; + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + bool isTrendFinishedFromBullish; + bool isTrendFinishedFromBearish; + + // + // SUPPORT ... + + // + bool isSupportSameLast; + bool isSupportOverLast; + bool isSupportUnderLast; + + // + bool isLastSupportBreaked; + bool isLastSupportRejected; + + // + // RESISTANCE ... + + // + bool isResistanceSameLast; + bool isResistanceOverLast; + bool isResistanceUnderLast; + + // + bool isLastResistanceBreaked; + bool isLastResistanceRejected; + + // + // SWING Low ... + + // + bool isSwingLowSameLast; + bool isSwingLowOverLast; + bool isSwingLowUnderLast; + + // + bool isLastSwingLowBreaked; + bool isLastSwingLowRejected; + + // + // SWING High ... + + // + bool isSwingHighSameLast; + bool isSwingHighOverLast; + bool isSwingHighUnderLast; + + // + bool isLastSwingHighBreaked; + bool isLastSwingHighRejected; + + // + // COMPLEX Conditions ... + + // + bool isPeakIsPivot; + bool isValeIsPivot; + + // + bool isPeakSwitchedToPivot; + bool isValeSwitchedToPivot; + + // + bool isPeakFinishedFromPivot; + bool isValeFinishedFromPivot; + + // + bool isSwingLowSameAsVale; + bool isSwingHighSameAsPeak; + + // + bool isSupportSameAsVale; + bool isResistanceSameAsPeak; + + // + bool isSupportSameAsSwingLow; + bool isResistanceSameAsSwingHigh; + + // + // Constructor ... + X121XCAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(kiBuffer); + Clean(tkiBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(sarBuffer); + Clean(mahBuffer); + Clean(malBuffer); + Clean(macBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(vidyaBuffer); + Clean(trendBuffer); + Clean(kiStateBuffer); + Clean(supportBuffer); + Clean(tkiStateBuffer); + Clean(swingLowBuffer); + Clean(swingHighBuffer); + Clean(resistanceBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(fiboLevel1Buffer); + Clean(fiboLevel2Buffer); + Clean(fiboLevel3Buffer); + Clean(fiboLevel4Buffer); + Clean(fiboLevel5Buffer); + Clean(vidyaStateBuffer); + Clean(trendStateBuffer); + + // + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(tkiBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(mahBuffer, true); + ArraySetAsSeries(malBuffer, true); + ArraySetAsSeries(macBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(vidyaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(supportBuffer, true); + ArraySetAsSeries(tkiStateBuffer, true); + ArraySetAsSeries(swingLowBuffer, true); + ArraySetAsSeries(swingHighBuffer, true); + ArraySetAsSeries(resistanceBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(fiboLevel1Buffer, true); + ArraySetAsSeries(fiboLevel2Buffer, true); + ArraySetAsSeries(fiboLevel3Buffer, true); + ArraySetAsSeries(fiboLevel4Buffer, true); + ArraySetAsSeries(fiboLevel5Buffer, true); + ArraySetAsSeries(vidyaStateBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + + // + // Conditions ... + + // + // KI ... + + // + isKIRejectUp = false; + isKIRejectDown = false; + + // + isKIBullish = false; + isKIBearish = false; + + // + isKISwitchedToBullish = false; + isKISwitchedToBearish = false; + + // + isKIFinishedFromBullish = false; + isKIFinishedFromBearish = false; + + // + // TKI ... + + // + isTKIRejectUp = false; + isTKIRejectDown = false; + + // + isTKIBullish = false; + isTKIBearish = false; + + // + isTKISwitchedToBullish = false; + isTKISwitchedToBearish = false; + + // + isTKIFinishedFromBullish = false; + isTKIFinishedFromBearish = false; + + // + // VIDYA ... + + // + isVidyaRejectUp = false; + isVidyaRejectDown = false; + + // + isVidyaBullish = false; + isVidyaBearish = false; + + // + isVidyaSwitchedToBullish = false; + isVidyaSwitchedToBearish = false; + + // + isVidyaFinishedFromBullish = false; + isVidyaFinishedFromBearish = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + isSarFinishedFromBullish = false; + isSarFinishedFromBearish = false; + + // + // MANALYSER ... + + // + // MAH ... + + // + isOverMah = false; + isUnderMah = false; + isCrossedOverMah = false; + isCrossedUnderMah = false; + + // + isCloseOverMah = false; + isCloseUnderMah = false; + isCloseCrossedOverMah = false; + isCloseCrossedUnderMah = false; + + // + isMahBullishRejected = false; + isMahBearishRejected = false; + + // + // MAL ... + + // + isOverMal = false; + isUnderMal = false; + isCrossedOverMal = false; + isCrossedUnderMal = false; + + // + isCloseOverMal = false; + isCloseUnderMal = false; + isCloseCrossedOverMal = false; + isCloseCrossedUnderMal = false; + + // + isMalBullishRejected = false; + isMalBearishRejected = false; + + // + // MAC ... + + // + isOverMac = false; + isUnderMac = false; + isCrossedOverMac = false; + isCrossedUnderMac = false; + + // + isCloseOverMac = false; + isCloseUnderMac = false; + isCloseCrossedOverMac = false; + isCloseCrossedUnderMac = false; + + // + isMacBullishRejected = false; + isMacBearishRejected = false; + + // + // PEAK ... + + // + isPeakSameLast = false; + isPeakOverLast = false; + isPeakUnderLast = false; + + // + // VALE ... + + // + isValeSameLast = false; + isValeOverLast = false; + isValeUnderLast = false; + + // + // TREND ... + + // + isTrendRejectUp = false; + isTrendRejectDown = false; + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + isTrendFinishedFromBullish = false; + isTrendFinishedFromBearish = false; + + // + // SUPPORT ... + + // + isSupportSameLast = false; + isSupportOverLast = false; + isSupportUnderLast = false; + + // + isLastSupportBreaked = false; + isLastSupportRejected = false; + + // + // RESISTANCE ... + + // + isResistanceSameLast = false; + isResistanceOverLast = false; + isResistanceUnderLast = false; + + // + isLastResistanceBreaked = false; + isLastResistanceRejected = false; + + // + // SWING Low ... + + // + isSwingLowSameLast = false; + isSwingLowOverLast = false; + isSwingLowUnderLast = false; + + // + isLastSwingLowBreaked = false; + isLastSwingLowRejected = false; + + // + // SWING High ... + + // + isSwingHighSameLast = false; + isSwingHighOverLast = false; + isSwingHighUnderLast = false; + + // + isLastSwingHighBreaked = false; + isLastSwingHighRejected = false; + + // + // COMPLEX Conditions ... + + // + isPeakIsPivot = false; + isValeIsPivot = false; + + // + isPeakSwitchedToPivot = false; + isValeSwitchedToPivot = false; + + // + isPeakFinishedFromPivot = false; + isValeFinishedFromPivot = false; + + // + isSwingLowSameAsVale = false; + isSwingHighSameAsPeak = false; + + // + isSupportSameAsVale = false; + isResistanceSameAsPeak = false; + + // + isSupportSameAsSwingLow = false; + isResistanceSameAsSwingHigh = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // KI ... + + // + if (isKIBullish) + { + bullishScore += minScore; + } + if (isKIRejectUp) + { + bullishScore += minScore; + } + if (isKISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isKIBearish) + { + bearishScore += minScore; + } + if (isKIRejectDown) + { + bearishScore += minScore; + } + if (isKISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // TKI ... + + // + if (isTKIBullish) + { + bullishScore += minScore; + } + if (isTKIRejectUp) + { + bullishScore += minScore; + } + if (isTKISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isTKIBearish) + { + bearishScore += minScore; + } + if (isTKIRejectDown) + { + bearishScore += minScore; + } + if (isTKISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // VIDYA ... + + // + if (isVidyaBullish) + { + bullishScore += minScore; + } + if (isVidyaRejectUp) + { + bullishScore += minScore; + } + if (isVidyaSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isVidyaBearish) + { + bearishScore += minScore; + } + if (isVidyaRejectDown) + { + bearishScore += minScore; + } + if (isVidyaSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // SAR ... + + // + if (isSarBullish) + { + bullishScore += minScore; + } + if (isSarSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isSarBearish) + { + bearishScore += minScore; + } + if (isSarSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // MANALYSER ... + + // + // MAH ... + + // + if (isUnderMah) + { + bullishScore += minScore; + } + if (isCloseUnderMah) + { + bullishScore += minScore; + } + if (isCrossedUnderMah) + { + bullishScore += minScore; + } + if (isMahBullishRejected) + { + bullishScore += minScore; + } + if (isCloseCrossedUnderMah) + { + bullishScore += minScore; + } + + // + if (isOverMah) + { + bearishScore += minScore; + } + if (isCloseOverMah) + { + bearishScore += minScore; + } + if (isCrossedOverMah) + { + bearishScore += minScore; + } + if (isMahBearishRejected) + { + bearishScore += minScore; + } + if (isCloseCrossedOverMah) + { + bearishScore += minScore; + } + + // + + // + // MAL ... + + // + if (isOverMal) + { + bullishScore += minScore; + } + if (isCloseOverMal) + { + bullishScore += minScore; + } + if (isCrossedOverMal) + { + bullishScore += minScore; + } + if (isMalBullishRejected) + { + bullishScore += minScore; + } + if (isCloseCrossedOverMal) + { + bullishScore += minScore; + } + + // + if (isUnderMal) + { + bearishScore += minScore; + } + if (isCloseUnderMal) + { + bearishScore += minScore; + } + if (isCrossedUnderMal) + { + bearishScore += minScore; + } + if (isMalBearishRejected) + { + bearishScore += minScore; + } + if (isCloseCrossedUnderMal) + { + bearishScore += minScore; + } + + // + // MAC ... + + // + if (isOverMac) + { + bullishScore += minScore; + } + if (isCloseOverMac) + { + bullishScore += minScore; + } + if (isCrossedOverMac) + { + bullishScore += minScore; + } + if (isMacBullishRejected) + { + bullishScore += minScore; + } + if (isCloseCrossedOverMac) + { + bullishScore += minScore; + } + + // + if (isUnderMac) + { + bearishScore += minScore; + } + if (isCloseUnderMac) + { + bearishScore += minScore; + } + if (isCrossedUnderMac) + { + bearishScore += minScore; + } + if (isMacBearishRejected) + { + bearishScore += minScore; + } + if (isCloseCrossedUnderMac) + { + bearishScore += minScore; + } + + // + // TREND ... + + // + if (isTrendBullish) + { + bullishScore += minScore; + } + if (isTrendRejectUp) + { + bullishScore += minScore; + } + if (isTrendSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isTrendBearish) + { + bearishScore += minScore; + } + if (isTrendRejectDown) + { + bearishScore += minScore; + } + if (isTrendSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // SUPPORT ... + + // + if (isSupportSameLast) + { + bullishScore += minScore; + } + if (isSupportOverLast) + { + bullishScore += minScore; + } + if (isLastSupportRejected) + { + bullishScore += minScore; + } + + // + if (isSupportUnderLast) + { + bearishScore += minScore; + } + if (isLastSupportBreaked) + { + bearishScore += minScore; + } + + // + // RESISTANCE ... + + // + if (isResistanceOverLast) + { + bullishScore += minScore; + } + if (isLastResistanceBreaked) + { + bullishScore += minScore; + } + + // + if (isResistanceSameLast) + { + bearishScore += minScore; + } + if (isResistanceUnderLast) + { + bearishScore += minScore; + } + if (isLastResistanceRejected) + { + bearishScore += minScore; + } + + // + // SWING Low ... + + // + if (isSwingLowSameLast) + { + bullishScore += minScore; + } + if (isSwingLowOverLast) + { + bullishScore += minScore; + } + if (isLastSwingLowRejected) + { + bullishScore += minScore; + } + + // + if (isSwingLowUnderLast) + { + bearishScore += minScore; + } + if (isLastSwingLowBreaked) + { + bearishScore += minScore; + } + + // + // SWING High ... + + // + if (isSwingHighOverLast) + { + bullishScore += minScore; + } + if (isLastSwingHighBreaked) + { + bullishScore += minScore; + } + + // + if (isSwingHighSameLast) + { + bearishScore += minScore; + } + if (isSwingHighUnderLast) + { + bearishScore += minScore; + } + if (isLastSwingHighRejected) + { + bearishScore += minScore; + } + + // + // COMPLEX Conditions ... + + // + if (isValeIsPivot) + { + bullishScore += score; + } + if (isSupportSameAsVale) + { + bullishScore += score; + } + if (isSwingLowSameAsVale) + { + bullishScore += score; + } + if (isSupportSameAsSwingLow) + { + bullishScore += score; + } + + // + if (isPeakIsPivot) + { + bearishScore += score; + } + if (isSwingHighSameAsPeak) + { + bearishScore += score; + } + if (isResistanceSameAsPeak) + { + bearishScore += score; + } + if (isResistanceSameAsSwingHigh) + { + bearishScore += score; + } + + // + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XCA: " + separator + + "-----------------------" + separator + + ToString("isKIRejectUp", isKIRejectUp, ignoreFalseConditions, separator) + + ToString("isKIRejectDown", isKIRejectDown, ignoreFalseConditions, separator) + + ToString("isKIBullish", isKIBullish, ignoreFalseConditions, separator) + + ToString("isKIBearish", isKIBearish, ignoreFalseConditions, separator) + + ToString("isKISwitchedToBullish", isKISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isKIFinishedFromBullish", isKIFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isKISwitchedToBearish", isKISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isKIFinishedFromBearish", isKIFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isTKIRejectUp", isTKIRejectUp, ignoreFalseConditions, separator) + + ToString("isTKIRejectDown", isTKIRejectDown, ignoreFalseConditions, separator) + + ToString("isTKIBullish", isTKIBullish, ignoreFalseConditions, separator) + + ToString("isTKIBearish", isTKIBearish, ignoreFalseConditions, separator) + + ToString("isTKISwitchedToBullish", isTKISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTKIFinishedFromBullish", isTKIFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isTKISwitchedToBearish", isTKISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isTKIFinishedFromBearish", isTKIFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isVidyaRejectUp", isVidyaRejectUp, ignoreFalseConditions, separator) + + ToString("isVidyaRejectDown", isVidyaRejectDown, ignoreFalseConditions, separator) + + ToString("isVidyaBullish", isVidyaBullish, ignoreFalseConditions, separator) + + ToString("isVidyaBearish", isVidyaBearish, ignoreFalseConditions, separator) + + ToString("isVidyaSwitchedToBullish", isVidyaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isVidyaFinishedFromBullish", isVidyaFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isVidyaSwitchedToBearish", isVidyaSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isVidyaFinishedFromBearish", isVidyaFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarFinishedFromBullish", isSarFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSarFinishedFromBearish", isSarFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isOverMah", isOverMah, ignoreFalseConditions, separator) + + ToString("isUnderMah", isUnderMah, ignoreFalseConditions, separator) + + ToString("isCrossedOverMah", isCrossedOverMah, ignoreFalseConditions, separator) + + ToString("isCrossedUnderMah", isCrossedUnderMah, ignoreFalseConditions, separator) + + ToString("isCloseOverMah", isCloseOverMah, ignoreFalseConditions, separator) + + ToString("isCloseUnderMah", isCloseUnderMah, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverMah", isCloseCrossedOverMah, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderMah", isCloseCrossedUnderMah, ignoreFalseConditions, separator) + + ToString("isMahBullishRejected", isMahBullishRejected, ignoreFalseConditions, separator) + + ToString("isMahBearishRejected", isMahBearishRejected, ignoreFalseConditions, separator) + + ToString("isOverMal", isOverMal, ignoreFalseConditions, separator) + + ToString("isUnderMal", isUnderMal, ignoreFalseConditions, separator) + + ToString("isCrossedOverMal", isCrossedOverMal, ignoreFalseConditions, separator) + + ToString("isCrossedUnderMal", isCrossedUnderMal, ignoreFalseConditions, separator) + + ToString("isCloseOverMal", isCloseOverMal, ignoreFalseConditions, separator) + + ToString("isCloseUnderMal", isCloseUnderMal, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverMal", isCloseCrossedOverMal, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderMal", isCloseCrossedUnderMal, ignoreFalseConditions, separator) + + ToString("isMalBullishRejected", isMalBullishRejected, ignoreFalseConditions, separator) + + ToString("isMalBearishRejected", isMalBearishRejected, ignoreFalseConditions, separator) + + ToString("isOverMac", isOverMac, ignoreFalseConditions, separator) + + ToString("isUnderMac", isUnderMac, ignoreFalseConditions, separator) + + ToString("isCrossedOverMac", isCrossedOverMac, ignoreFalseConditions, separator) + + ToString("isCrossedUnderMac", isCrossedUnderMac, ignoreFalseConditions, separator) + + ToString("isCloseOverMac", isCloseOverMac, ignoreFalseConditions, separator) + + ToString("isCloseUnderMac", isCloseUnderMac, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverMac", isCloseCrossedOverMac, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderMac", isCloseCrossedUnderMac, ignoreFalseConditions, separator) + + ToString("isMacBullishRejected", isMacBullishRejected, ignoreFalseConditions, separator) + + ToString("isMacBearishRejected", isMacBearishRejected, ignoreFalseConditions, separator) + + ToString("isPeakSameLast", isPeakSameLast, ignoreFalseConditions, separator) + + ToString("isPeakOverLast", isPeakOverLast, ignoreFalseConditions, separator) + + ToString("isPeakUnderLast", isPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isValeSameLast", isValeSameLast, ignoreFalseConditions, separator) + + ToString("isValeOverLast", isValeOverLast, ignoreFalseConditions, separator) + + ToString("isValeUnderLast", isValeUnderLast, ignoreFalseConditions, separator) + + ToString("isTrendRejectUp", isTrendRejectUp, ignoreFalseConditions, separator) + + ToString("isTrendRejectDown", isTrendRejectDown, ignoreFalseConditions, separator) + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendFinishedFromBullish", isTrendFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isTrendFinishedFromBearish", isTrendFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isSupportSameLast", isSupportSameLast, ignoreFalseConditions, separator) + + ToString("isSupportOverLast", isSupportOverLast, ignoreFalseConditions, separator) + + ToString("isSupportUnderLast", isSupportUnderLast, ignoreFalseConditions, separator) + + ToString("isLastSupportBreaked", isLastSupportBreaked, ignoreFalseConditions, separator) + + ToString("isLastSupportRejected", isLastSupportRejected, ignoreFalseConditions, separator) + + ToString("isResistanceSameLast", isResistanceSameLast, ignoreFalseConditions, separator) + + ToString("isResistanceOverLast", isResistanceOverLast, ignoreFalseConditions, separator) + + ToString("isResistanceUnderLast", isResistanceUnderLast, ignoreFalseConditions, separator) + + ToString("isLastResistanceBreaked", isLastResistanceBreaked, ignoreFalseConditions, separator) + + ToString("isLastResistanceRejected", isLastResistanceRejected, ignoreFalseConditions, separator) + + ToString("isSwingLowSameLast", isSwingLowSameLast, ignoreFalseConditions, separator) + + ToString("isSwingLowOverLast", isSwingLowOverLast, ignoreFalseConditions, separator) + + ToString("isSwingLowUnderLast", isSwingLowUnderLast, ignoreFalseConditions, separator) + + ToString("isLastSwingLowBreaked", isLastSwingLowBreaked, ignoreFalseConditions, separator) + + ToString("isLastSwingLowRejected", isLastSwingLowRejected, ignoreFalseConditions, separator) + + ToString("isSwingHighSameLast", isSwingHighSameLast, ignoreFalseConditions, separator) + + ToString("isSwingHighOverLast", isSwingHighOverLast, ignoreFalseConditions, separator) + + ToString("isSwingHighUnderLast", isSwingHighUnderLast, ignoreFalseConditions, separator) + + ToString("isLastSwingHighBreaked", isLastSwingHighBreaked, ignoreFalseConditions, separator) + + ToString("isLastSwingHighRejected", isLastSwingHighRejected, ignoreFalseConditions, separator) + + ToString("isPeakIsPivot", isPeakIsPivot, ignoreFalseConditions, separator) + + ToString("isValeIsPivot", isValeIsPivot, ignoreFalseConditions, separator) + + ToString("isPeakSwitchedToPivot", isPeakSwitchedToPivot, ignoreFalseConditions, separator) + + ToString("isPeakFinishedFromPivot", isPeakFinishedFromPivot, ignoreFalseConditions, separator) + + ToString("isValeSwitchedToPivot", isValeSwitchedToPivot, ignoreFalseConditions, separator) + + ToString("isValeFinishedFromPivot", isValeFinishedFromPivot, ignoreFalseConditions, separator) + + ToString("isSwingLowSameAsVale", isSwingLowSameAsVale, ignoreFalseConditions, separator) + + ToString("isSwingHighSameAsPeak", isSwingHighSameAsPeak, ignoreFalseConditions, separator) + + ToString("isSupportSameAsVale", isSupportSameAsVale, ignoreFalseConditions, separator) + + ToString("isResistanceSameAsPeak", isResistanceSameAsPeak, ignoreFalseConditions, separator) + + ToString("isSupportSameAsSwingLow", isSupportSameAsSwingLow, ignoreFalseConditions, separator) + + ToString("isResistanceSameAsSwingHigh", isResistanceSameAsSwingHigh, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCAHelper() + { + // + mInputs.Clean(); + + // + Clean(kiBuffer); + Clean(tkiBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(sarBuffer); + Clean(mahBuffer); + Clean(malBuffer); + Clean(macBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(vidyaBuffer); + Clean(trendBuffer); + Clean(kiStateBuffer); + Clean(supportBuffer); + Clean(tkiStateBuffer); + Clean(swingLowBuffer); + Clean(swingHighBuffer); + Clean(resistanceBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(fiboLevel1Buffer); + Clean(fiboLevel2Buffer); + Clean(fiboLevel3Buffer); + Clean(fiboLevel4Buffer); + Clean(fiboLevel5Buffer); + Clean(trendStateBuffer); + Clean(vidyaStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(tkiBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(mahBuffer, true); + ArraySetAsSeries(malBuffer, true); + ArraySetAsSeries(macBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(vidyaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(supportBuffer, true); + ArraySetAsSeries(tkiStateBuffer, true); + ArraySetAsSeries(swingLowBuffer, true); + ArraySetAsSeries(swingHighBuffer, true); + ArraySetAsSeries(resistanceBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(fiboLevel1Buffer, true); + ArraySetAsSeries(fiboLevel2Buffer, true); + ArraySetAsSeries(fiboLevel3Buffer, true); + ArraySetAsSeries(fiboLevel4Buffer, true); + ArraySetAsSeries(fiboLevel5Buffer, true); + ArraySetAsSeries(vidyaStateBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xca", + "", // Market ... + "", // Short ... + mInputs.scMethod, + mInputs.scPeriod, + "", // Medium ... + mInputs.mcMethod, + mInputs.mcPeriod, + "", // Long ... + mInputs.lcMethod, + mInputs.lcPeriod, + "", // Hind ... + mInputs.hcMethod, + mInputs.hcPeriod, + "", // Boundary Detection ... + mInputs.hhMode, + mInputs.llMode, + "", // Fibo Levels ... + mInputs.fiboLevel1, + mInputs.fiboLevel2, + mInputs.fiboLevel3, + mInputs.fiboLevel4, + mInputs.fiboLevel5, + "", // Sar Detection ... + mInputs.sarStep, + mInputs.sarMax, + "", // KI ... + mInputs.kiLength, + "", // VIDYA ... + mInputs.vidyaCMOLength, + mInputs.vidyaEMALength, + mInputs.vidyaAppliedTo, + "", // MANALYSER ... + mInputs.manalyserLength, + mInputs.manalyserMethod, + "", // Swing Detection ... + mInputs.swingLength, + "", // Support and Resistance ... + mInputs.supResSmoothingLength, + mInputs.supResSmoothingMode, + "", // Presentation ... + mInputs.startCalculationForLastBars, + mInputs.showSar, + mInputs.showKI, + mInputs.showTKI, + mInputs.showMAH, + mInputs.showMAL, + mInputs.showMAC, + mInputs.showVidya, + mInputs.showTrend, + mInputs.showSwings, + mInputs.showFiboLevel1, + mInputs.showFiboLevel2, + mInputs.showFiboLevel3, + mInputs.showFiboLevel4, + mInputs.showFiboLevel5, + mInputs.showPeaksAndVales, + mInputs.showPeakAndValeGolden, + mInputs.showSupportAndResistance // + // mInputs.showShortCycle, + // mInputs.showMediumCycle, + // mInputs.showLongCycle, + // mInputs.showHindCycle // , + // + // mInputs.sarArrowCode, + // mInputs.peakArrowCode, + // mInputs.valeArrowCode, + // mInputs.swingLowArrowCode, + // mInputs.swingHighArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // KI ... + + // + double GetKI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiBuffer[barIndex]; + } + + // + int CopyKI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiBuffer, + buffer, + forceClean + // + ); + } + + // + // KI STATE ... + + // + double GetKIState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiStateBuffer[barIndex]; + } + + // + int CopyKIState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiStateBuffer, + buffer, + forceClean + // + ); + } + + // + // TKI ... + + // + double GetTKI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(tkiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return tkiBuffer[barIndex]; + } + + // + int CopyTKI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + tkiBuffer, + buffer, + forceClean + // + ); + } + + // + // TKI STATE ... + + // + double GetTKIState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(tkiStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return tkiStateBuffer[barIndex]; + } + + // + int CopyTKIState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + tkiStateBuffer, + buffer, + forceClean + // + ); + } + + // + // VIDYA ... + + // + double GetVidya( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(vidyaBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vidyaBuffer[barIndex]; + } + + // + int CopyVidya( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + vidyaBuffer, + buffer, + forceClean + // + ); + } + + // + // VIDYA STATE ... + + // + double GetVidyaState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(vidyaStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vidyaStateBuffer[barIndex]; + } + + // + int CopyVidyaState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + vidyaStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // MANALYSER ... + + // + // MAH ... + + // + double GetMah( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mahBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mahBuffer[barIndex]; + } + + // + int CopyMah( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mahBuffer, + buffer, + forceClean + // + ); + } + + // + // MAL ,,, + + // + double GetMal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(malBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return malBuffer[barIndex]; + } + + // + int CopyMal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + malBuffer, + buffer, + forceClean + // + ); + } + + // + // MAC ... + + // + double GetMac( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(macBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return macBuffer[barIndex]; + } + + // + int CopyMac( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + macBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK Golden ... + + // + double GetPeakGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakGoldenBuffer[barIndex]; + } + + // + int CopyPeakGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE Golden ... + + // + double GetValeGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeGoldenBuffer[barIndex]; + } + + // + int CopyValeGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendBuffer[barIndex]; + } + + // + int CopyTrend( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrendState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendStateBuffer[barIndex]; + } + + // + int CopyTrendState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SUPPORT ... + + // + double GetSupport( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(supportBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return supportBuffer[barIndex]; + } + + // + int CopySupport( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + supportBuffer, + buffer, + forceClean + // + ); + } + + // + // RESISTANCE ... + + // + double GetResistance( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(resistanceBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return resistanceBuffer[barIndex]; + } + + // + int CopyResistance( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + resistanceBuffer, + buffer, + forceClean + // + ); + } + + // + // SWING Low ... + + // + double GetSwingLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(swingLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return swingLowBuffer[barIndex]; + } + + // + int CopySwingLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + swingLowBuffer, + buffer, + forceClean + // + ); + } + + // + // SWING High ... + + // + double GetSwingHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(swingHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return swingHighBuffer[barIndex]; + } + + // + int CopySwingHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + swingHighBuffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 1 ... + + // + double GetFiboLevel1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel1Buffer[barIndex]; + } + + // + int CopyFiboLevel1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel1Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 2 ... + + // + double GetFiboLevel2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel2Buffer[barIndex]; + } + + // + int CopyFiboLevel2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel2Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 3 ... + + // + double GetFiboLevel3( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel3Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel3Buffer[barIndex]; + } + + // + int CopyFiboLevel3( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel3Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 4 ... + + // + double GetFiboLevel4( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel4Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel4Buffer[barIndex]; + } + + // + int CopyFiboLevel4( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel4Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 5 ... + + // + double GetFiboLevel5( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel5Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel5Buffer[barIndex]; + } + + // + int CopyFiboLevel5( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel5Buffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + CopyKI( + zIndex, + loopback, + conditions.kiBuffer // + ); + + // + CopyKIState( + zIndex, + loopback, + conditions.kiStateBuffer // + ); + + // + CopyTKI( + zIndex, + loopback, + conditions.tkiBuffer // + ); + + // + CopyTKIState( + zIndex, + loopback, + conditions.tkiStateBuffer // + ); + + // + CopyVidya( + zIndex, + loopback, + conditions.vidyaBuffer // + ); + + // + CopyVidyaState( + zIndex, + loopback, + conditions.vidyaStateBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopyMah( + zIndex, + loopback, + conditions.mahBuffer // + ); + + // + CopyMal( + zIndex, + loopback, + conditions.malBuffer // + ); + + // + CopyMac( + zIndex, + loopback, + conditions.macBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyPeakGolden( + zIndex, + loopback, + conditions.peakGoldenBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyValeGolden( + zIndex, + loopback, + conditions.valeGoldenBuffer // + ); + + // + CopyTrend( + zIndex, + loopback, + conditions.trendBuffer // + ); + + // + CopyTrendState( + zIndex, + loopback, + conditions.trendStateBuffer // + ); + + // + CopySupport( + zIndex, + loopback, + conditions.supportBuffer // + ); + + // + CopyResistance( + zIndex, + loopback, + conditions.resistanceBuffer // + ); + + // + CopySwingLow( + zIndex, + loopback, + conditions.swingLowBuffer // + ); + + // + CopySwingHigh( + zIndex, + loopback, + conditions.swingHighBuffer // + ); + + // + CopyFiboLevel1( + zIndex, + loopback, + conditions.fiboLevel1Buffer // + ); + + // + CopyFiboLevel2( + zIndex, + loopback, + conditions.fiboLevel2Buffer // + ); + + // + CopyFiboLevel3( + zIndex, + loopback, + conditions.fiboLevel3Buffer // + ); + + // + CopyFiboLevel4( + zIndex, + loopback, + conditions.fiboLevel4Buffer // + ); + + // + CopyFiboLevel5( + zIndex, + loopback, + conditions.fiboLevel5Buffer // + ); + + // + // Conditions ... + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Calculate ... + + // + // KI ... + + // + double cKI = conditions.kiBuffer[cIDX]; + double pKI = conditions.kiBuffer[pIDX]; + double p2KI = conditions.kiBuffer[p2IDX]; + + // + double cKIState = conditions.kiStateBuffer[cIDX]; + double pKIState = conditions.kiStateBuffer[pIDX]; + double p2KIState = conditions.kiStateBuffer[p2IDX]; + + // + bool isKIRejectUp = cBar.IsRejected( + cKI, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isKIRejectDown = cBar.IsRejected( + cKI, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isKIBullish = cKIState > 0; + bool isKIBullishPrev = pKIState > 0; + + // + bool isKIBearish = cKIState < 0; + bool isKIBearishPrev = pKIState < 0; + + // + bool isKISwitchedToBullish = isKIBullish && + !isKIBullishPrev; + bool isKIFinishedFromBullish = !isKIBullish && + isKIBullishPrev; + + // + bool isKISwitchedToBearish = isKIBearish && + !isKIBearishPrev; + bool isKIFinishedFromBearish = !isKIBearish && + isKIBearishPrev; + + // + // TKI ... + + // + double cTKI = conditions.tkiBuffer[cIDX]; + double pTKI = conditions.tkiBuffer[pIDX]; + double p2TKI = conditions.tkiBuffer[p2IDX]; + + // + double cTKIState = conditions.tkiStateBuffer[cIDX]; + double pTKIState = conditions.tkiStateBuffer[pIDX]; + double p2TKIState = conditions.tkiStateBuffer[p2IDX]; + + // + bool isTKIRejectUp = cBar.IsRejected( + cTKI, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isTKIRejectDown = cBar.IsRejected( + cTKI, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isTKIBullish = cTKIState > 0; + bool isTKIBullishPrev = pTKIState > 0; + + // + bool isTKIBearish = cTKIState < 0; + bool isTKIBearishPrev = pTKIState < 0; + + // + bool isTKISwitchedToBullish = isTKIBullish && + !isTKIBullishPrev; + bool isTKIFinishedFromBullish = !isTKIBullish && + isTKIBullishPrev; + + // + bool isTKISwitchedToBearish = isTKIBearish && + !isTKIBearishPrev; + bool isTKIFinishedFromBearish = !isTKIBearish && + isTKIBearishPrev; + + // + // VIDYA ... + + // + double cVidya = conditions.vidyaBuffer[cIDX]; + double pVidya = conditions.vidyaBuffer[pIDX]; + double p2Vidya = conditions.vidyaBuffer[p2IDX]; + + // + double cVidyaState = conditions.vidyaStateBuffer[cIDX]; + double pVidyaState = conditions.vidyaStateBuffer[pIDX]; + double p2VidyaState = conditions.vidyaStateBuffer[p2IDX]; + + // + bool isVidyaRejectUp = cBar.IsRejected( + cVidya, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isVidyaRejectDown = cBar.IsRejected( + cVidya, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isVidyaBullish = cVidyaState > 0; + bool isVidyaBullishPrev = pVidyaState > 0; + + // + bool isVidyaBearish = cVidyaState < 0; + bool isVidyaBearishPrev = pVidyaState < 0; + + // + bool isVidyaSwitchedToBullish = isVidyaBullish && + !isVidyaBullishPrev; + bool isVidyaFinishedFromBullish = !isVidyaBullish && + isVidyaBullishPrev; + + // + bool isVidyaSwitchedToBearish = isVidyaBearish && + !isVidyaBearishPrev; + bool isVidyaFinishedFromBearish = !isVidyaBearish && + isVidyaBearishPrev; + + // + // SAR ... + + // + double cSar = conditions.sarBuffer[cIDX]; + double pSar = conditions.sarBuffer[pIDX]; + + // + bool isSarBullish = cBar.low > cSar; + bool isSarBullishPrev = pBar.low > pSar; + + // + bool isSarBearish = cBar.high < cSar; + bool isSarBearishPrev = pBar.high < pSar; + + // + bool isSarSwitchedToBullish = isSarBullish && + !isSarBullishPrev; + bool isSarFinishedFromBullish = !isSarBullish && + isSarBullishPrev; + + // + bool isSarSwitchedToBearish = isSarBearish && + !isSarBearishPrev; + bool isSarFinishedFromBearish = !isSarBearish && + isSarBearishPrev; + + // + // MANALYSER ... + + // + // MAH ... + + // + bool isOverMah = cBar.low > conditions.mahBuffer[cIDX]; + bool isOverMahPrev = pBar.low > conditions.mahBuffer[pIDX]; + + // + bool isUnderMah = cBar.high < conditions.mahBuffer[cIDX]; + bool isUnderMahPrev = pBar.high < conditions.mahBuffer[pIDX]; + + // + bool isCrossedOverMah = isOverMah && + !isOverMahPrev; + bool isCrossedUnderMah = isUnderMah && + !isUnderMahPrev; + + // + bool isCloseOverMah = cBar.close > conditions.mahBuffer[cIDX]; + bool isCloseOverMahPrev = pBar.close > conditions.mahBuffer[pIDX]; + + bool isCloseUnderMah = cBar.close < conditions.mahBuffer[cIDX]; + bool isCloseUnderMahPrev = pBar.close < conditions.mahBuffer[pIDX]; + + // + bool isCloseCrossedOverMah = isCloseOverMah && + !isCloseOverMahPrev; + bool isCloseCrossedUnderMah = isCloseUnderMah && + !isCloseUnderMahPrev; + + // + bool isMahBullishRejected = cBar.IsRejected( + conditions.mahBuffer[cIDX], + X_DIRECTION_BULLISH, + false, + false // + ); + bool isMahBearishRejected = cBar.IsRejected( + conditions.mahBuffer[cIDX], + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // MAL ... + + // + bool isOverMal = cBar.low > conditions.malBuffer[cIDX]; + bool isOverMalPrev = pBar.low > conditions.malBuffer[pIDX]; + + // + bool isUnderMal = cBar.high < conditions.malBuffer[cIDX]; + bool isUnderMalPrev = pBar.high < conditions.malBuffer[pIDX]; + + // + bool isCrossedOverMal = isOverMal && + !isOverMalPrev; + bool isCrossedUnderMal = isUnderMal && + !isUnderMalPrev; + + // + bool isCloseOverMal = cBar.close > conditions.malBuffer[cIDX]; + bool isCloseOverMalPrev = pBar.close > conditions.malBuffer[pIDX]; + + bool isCloseUnderMal = cBar.close < conditions.malBuffer[cIDX]; + bool isCloseUnderMalPrev = pBar.close < conditions.malBuffer[pIDX]; + + // + bool isCloseCrossedOverMal = isCloseOverMal && + !isCloseOverMalPrev; + bool isCloseCrossedUnderMal = isCloseUnderMal && + !isCloseUnderMalPrev; + + // + bool isMalBullishRejected = cBar.IsRejected( + conditions.malBuffer[cIDX], + X_DIRECTION_BULLISH, + false, + false // + ); + bool isMalBearishRejected = cBar.IsRejected( + conditions.malBuffer[cIDX], + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // MAC ... + + // + bool isOverMac = cBar.low > conditions.macBuffer[cIDX]; + bool isOverMacPrev = pBar.low > conditions.macBuffer[pIDX]; + + // + bool isUnderMac = cBar.high < conditions.macBuffer[cIDX]; + bool isUnderMacPrev = pBar.high < conditions.macBuffer[pIDX]; + + // + bool isCrossedOverMac = isOverMac && + !isOverMacPrev; + bool isCrossedUnderMac = isUnderMac && + !isUnderMacPrev; + + // + bool isCloseOverMac = cBar.close > conditions.macBuffer[cIDX]; + bool isCloseOverMacPrev = pBar.close > conditions.macBuffer[pIDX]; + + bool isCloseUnderMac = cBar.close < conditions.macBuffer[cIDX]; + bool isCloseUnderMacPrev = pBar.close < conditions.macBuffer[pIDX]; + + // + bool isCloseCrossedOverMac = isCloseOverMac && + !isCloseOverMacPrev; + bool isCloseCrossedUnderMac = isCloseUnderMac && + !isCloseUnderMacPrev; + + // + bool isMacBullishRejected = cBar.IsRejected( + conditions.macBuffer[cIDX], + X_DIRECTION_BULLISH, + false, + false // + ); + bool isMacBearishRejected = cBar.IsRejected( + conditions.macBuffer[cIDX], + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // PEAK ... + + // + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + + // + bool isPeakSameLast = cPeak == pPeak; + bool isPeakOverLast = cPeak > pPeak; + bool isPeakUnderLast = cPeak < pPeak; + + // + // VALE ... + + // + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + + // + bool isValeSameLast = cVale == pVale; + bool isValeOverLast = cVale > pVale; + bool isValeUnderLast = cVale < pVale; + + // + // TREND ... + + // + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + + // + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + + // + bool isTrendRejectUp = cBar.IsRejected( + cTrend, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isTrendRejectDown = cBar.IsRejected( + cTrend, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isTrendBullish = cTrendState > 0; + bool isTrendBullishPrev = pTrendState > 0; + + // + bool isTrendBearish = cTrendState < 0; + bool isTrendBearishPrev = pTrendState < 0; + + // + bool isTrendSwitchedToBullish = isTrendBullish && + !isTrendBullishPrev; + bool isTrendFinishedFromBullish = !isTrendBullish && + isTrendBullishPrev; + + // + bool isTrendSwitchedToBearish = isTrendBearish && + !isTrendBearishPrev; + bool isTrendFinishedFromBearish = !isTrendBearish && + isTrendBearishPrev; + + // + // SUPPORT ... + + // + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + + // + bool isSupportSameLast = cSupport == pSupport; + bool isSupportOverLast = cSupport > pSupport; + bool isSupportUnderLast = cSupport < pSupport; + + // + bool isLastSupportBreaked = cBar.IsBreaked( + pSupport, + X_DIRECTION_BEARISH // + ); + bool isLastSupportRejected = cBar.IsRejected( + pSupport, + X_DIRECTION_BULLISH, + false, + false // + ); + + // + // RESISTANCE ... + + // + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + + // + bool isResistanceSameLast = cResistance == pResistance; + bool isResistanceOverLast = cResistance > pResistance; + bool isResistanceUnderLast = cResistance < pResistance; + + // + bool isLastResistanceBreaked = cBar.IsBreaked( + pResistance, + X_DIRECTION_BULLISH // + ); + bool isLastResistanceRejected = cBar.IsRejected( + pResistance, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // SWING Low ... + + // + double cSwingLow = conditions.swingLowBuffer[cIDX]; + double pSwingLow = conditions.swingLowBuffer[pIDX]; + + // + bool isSwingLowSameLast = cSwingLow == pSwingLow; + bool isSwingLowOverLast = cSwingLow > pSwingLow; + bool isSwingLowUnderLast = cSwingLow < pSwingLow; + + // + bool isLastSwingLowBreaked = cBar.IsBreaked( + pSwingLow, + X_DIRECTION_BEARISH // + ); + bool isLastSwingLowRejected = cBar.IsRejected( + pSwingLow, + X_DIRECTION_BULLISH, + false, + false // + ); + + // + // SWING High ... + + // + double cSwingHigh = conditions.swingHighBuffer[cIDX]; + double pSwingHigh = conditions.swingHighBuffer[pIDX]; + + // + bool isSwingHighSameLast = cSwingHigh == pSwingHigh; + bool isSwingHighOverLast = cSwingHigh > pSwingHigh; + bool isSwingHighUnderLast = cSwingHigh < pSwingHigh; + + // + bool isLastSwingHighBreaked = cBar.IsBreaked( + pSwingHigh, + X_DIRECTION_BULLISH // + ); + bool isLastSwingHighRejected = cBar.IsRejected( + pSwingHigh, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // COMPLEX Conditions ... + + // + bool isSwingLowSameAsVale = cSwingLow == cVale; + bool isSwingLowSameAsValePrev = pSwingLow == pVale; + + // + bool isSwingHighSameAsPeak = cSwingHigh == cPeak; + bool isSwingHighSameAsPeakPrev = pSwingHigh == pPeak; + + // + bool isSupportSameAsVale = cSupport == cVale; + bool isSupportSameAsValePrev = pSupport == pVale; + + // + bool isResistanceSameAsPeak = cResistance == cPeak; + bool isResistanceSameAsPeakPrev = pResistance == pPeak; + + // + bool isSupportSameAsSwingLow = cSupport == cSwingLow; + bool isSupportSameAsSwingLowPrev = pSupport == pSwingLow; + + // + bool isResistanceSameAsSwingHigh = cResistance == cSwingHigh; + bool isResistanceSameAsSwingHighPrev = pResistance == pSwingHigh; + + // + bool isPeakIsPivot = isSwingHighSameAsPeak && + isResistanceSameAsPeak && + isResistanceSameAsSwingHigh; + bool isPeakIsPivotPrev = isSwingHighSameAsPeakPrev && + isResistanceSameAsPeakPrev && + isResistanceSameAsSwingHighPrev; + + // + bool isPeakSwitchedToPivot = isPeakIsPivot && + !isPeakIsPivotPrev; + + // + bool isPeakFinishedFromPivot = !isPeakIsPivot && + isPeakIsPivotPrev; + + // + bool isValeIsPivot = isSwingLowSameAsVale && + isSupportSameAsVale && + isSupportSameAsSwingLow; + bool isValeIsPivotPrev = isSwingLowSameAsValePrev && + isSupportSameAsValePrev && + isSupportSameAsSwingLowPrev; + + // + bool isValeSwitchedToPivot = isValeIsPivot && + !isValeIsPivotPrev; + bool isValeFinishedFromPivot = !isValeIsPivot && + isValeIsPivotPrev; + // + // Attached ... + + // + conditions.isOverMah = isOverMah; + conditions.isOverMal = isOverMal; + conditions.isOverMac = isOverMac; + conditions.isUnderMah = isUnderMah; + conditions.isUnderMal = isUnderMal; + conditions.isUnderMac = isUnderMac; + conditions.isKIBullish = isKIBullish; + conditions.isKIBearish = isKIBearish; + conditions.isKIRejectUp = isKIRejectUp; + conditions.isTKIBullish = isTKIBullish; + conditions.isTKIBearish = isTKIBearish; + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isTKIRejectUp = isTKIRejectUp; + conditions.isPeakIsPivot = isPeakIsPivot; + conditions.isValeIsPivot = isValeIsPivot; + conditions.isCloseOverMah = isCloseOverMah; + conditions.isCloseOverMal = isCloseOverMal; + conditions.isCloseOverMac = isCloseOverMac; + conditions.isVidyaBullish = isVidyaBullish; + conditions.isVidyaBearish = isVidyaBearish; + conditions.isKIRejectDown = isKIRejectDown; + conditions.isPeakSameLast = isPeakSameLast; + conditions.isPeakOverLast = isPeakOverLast; + conditions.isValeSameLast = isValeSameLast; + conditions.isValeOverLast = isValeOverLast; + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isCloseUnderMah = isCloseUnderMah; + conditions.isCloseUnderMal = isCloseUnderMal; + conditions.isCloseUnderMac = isCloseUnderMac; + conditions.isTKIRejectDown = isTKIRejectDown; + conditions.isPeakUnderLast = isPeakUnderLast; + conditions.isValeUnderLast = isValeUnderLast; + conditions.isTrendRejectUp = isTrendRejectUp; + conditions.isCrossedOverMah = isCrossedOverMah; + conditions.isCrossedOverMal = isCrossedOverMal; + conditions.isCrossedOverMac = isCrossedOverMac; + conditions.isCrossedUnderMah = isCrossedUnderMah; + conditions.isCrossedUnderMal = isCrossedUnderMal; + conditions.isCrossedUnderMac = isCrossedUnderMac; + conditions.isTrendRejectDown = isTrendRejectDown; + conditions.isSupportSameLast = isSupportSameLast; + conditions.isSupportOverLast = isSupportOverLast; + conditions.isSupportUnderLast = isSupportUnderLast; + conditions.isSwingLowSameLast = isSwingLowSameLast; + conditions.isSwingLowOverLast = isSwingLowOverLast; + conditions.isSwingLowUnderLast = isSwingLowUnderLast; + conditions.isSwingHighSameLast = isSwingHighSameLast; + conditions.isSwingHighOverLast = isSwingHighOverLast; + conditions.isSupportSameAsVale = isSupportSameAsVale; + conditions.isMahBullishRejected = isMahBullishRejected; + conditions.isMahBearishRejected = isMahBearishRejected; + conditions.isMalBullishRejected = isMalBullishRejected; + conditions.isMalBearishRejected = isMalBearishRejected; + conditions.isMacBullishRejected = isMacBullishRejected; + conditions.isMacBearishRejected = isMacBearishRejected; + conditions.isLastSupportBreaked = isLastSupportBreaked; + conditions.isResistanceSameLast = isResistanceSameLast; + conditions.isResistanceOverLast = isResistanceOverLast; + conditions.isSwingHighUnderLast = isSwingHighUnderLast; + conditions.isSwingLowSameAsVale = isSwingLowSameAsVale; + conditions.isCloseCrossedOverMah = isCloseCrossedOverMah; + conditions.isCloseCrossedOverMal = isCloseCrossedOverMal; + conditions.isCloseCrossedOverMac = isCloseCrossedOverMac; + conditions.isLastSupportRejected = isLastSupportRejected; + conditions.isResistanceUnderLast = isResistanceUnderLast; + conditions.isKISwitchedToBullish = isKISwitchedToBullish; + conditions.isKISwitchedToBearish = isKISwitchedToBearish; + conditions.isLastSwingLowBreaked = isLastSwingLowBreaked; + conditions.isSwingHighSameAsPeak = isSwingHighSameAsPeak; + conditions.isPeakSwitchedToPivot = isPeakSwitchedToPivot; + conditions.isValeSwitchedToPivot = isValeSwitchedToPivot; + conditions.isCloseCrossedUnderMah = isCloseCrossedUnderMah; + conditions.isCloseCrossedUnderMal = isCloseCrossedUnderMal; + conditions.isCloseCrossedUnderMac = isCloseCrossedUnderMac; + conditions.isTKISwitchedToBullish = isTKISwitchedToBullish; + conditions.isTKISwitchedToBearish = isTKISwitchedToBearish; + conditions.isLastSwingLowRejected = isLastSwingLowRejected; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isLastSwingHighBreaked = isLastSwingHighBreaked; + conditions.isResistanceSameAsPeak = isResistanceSameAsPeak; + conditions.isPeakFinishedFromPivot = isPeakFinishedFromPivot; + conditions.isValeFinishedFromPivot = isValeFinishedFromPivot; + conditions.isLastSwingHighRejected = isLastSwingHighRejected; + conditions.isLastResistanceBreaked = isLastResistanceBreaked; + conditions.isSupportSameAsSwingLow = isSupportSameAsSwingLow; + conditions.isKIFinishedFromBullish = isKIFinishedFromBullish; + conditions.isKIFinishedFromBearish = isKIFinishedFromBearish; + conditions.isTKIFinishedFromBullish = isTKIFinishedFromBullish; + conditions.isTKIFinishedFromBearish = isTKIFinishedFromBearish; + conditions.isSarFinishedFromBullish = isSarFinishedFromBullish; + conditions.isSarFinishedFromBearish = isSarFinishedFromBearish; + conditions.isVidyaSwitchedToBullish = isVidyaSwitchedToBullish; + conditions.isVidyaSwitchedToBearish = isVidyaSwitchedToBearish; + conditions.isLastResistanceRejected = isLastResistanceRejected; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + conditions.isVidyaFinishedFromBullish = isVidyaFinishedFromBullish; + conditions.isVidyaFinishedFromBearish = isVidyaFinishedFromBearish; + conditions.isTrendFinishedFromBullish = isTrendFinishedFromBullish; + conditions.isTrendFinishedFromBearish = isTrendFinishedFromBearish; + conditions.isResistanceSameAsSwingHigh = isResistanceSameAsSwingHigh; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCAInputs mInputs; // Inputs ... + + // + // Buffers ... + double kiBuffer[]; + double tkiBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double sarBuffer[]; + double mahBuffer[]; + double malBuffer[]; + double macBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double vidyaBuffer[]; + double trendBuffer[]; + double kiStateBuffer[]; + double supportBuffer[]; + double tkiStateBuffer[]; + double swingLowBuffer[]; + double swingHighBuffer[]; + double resistanceBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double fiboLevel1Buffer[]; + double fiboLevel2Buffer[]; + double fiboLevel3Buffer[]; + double fiboLevel4Buffer[]; + double fiboLevel5Buffer[]; + double vidyaStateBuffer[]; + double trendStateBuffer[]; + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + X121_XCA_KI_LINE, + barIndex, + maxRequiredBars, + kiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TKI_LINE, + barIndex, + maxRequiredBars, + tkiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VIDYA_LINE, + barIndex, + maxRequiredBars, + vidyaBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_S_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_S_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_M_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_M_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_L_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_L_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_H_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_H_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_MAH_LINE, + barIndex, + maxRequiredBars, + mahBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_MAL_LINE, + barIndex, + maxRequiredBars, + malBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_MAC_LINE, + barIndex, + maxRequiredBars, + macBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TREND_LINE, + barIndex, + maxRequiredBars, + trendBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_KI_STATE_LINE, + barIndex, + maxRequiredBars, + kiStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TKI_STATE_LINE, + barIndex, + maxRequiredBars, + tkiStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VIDYA_STATE_LINE, + barIndex, + maxRequiredBars, + vidyaStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SUPPORT_LINE, + barIndex, + maxRequiredBars, + supportBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SWING_LOW_LINE, + barIndex, + maxRequiredBars, + swingLowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SWING_HIGH_LINE, + barIndex, + maxRequiredBars, + swingHighBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_RESISTANCE_LINE, + barIndex, + maxRequiredBars, + resistanceBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_PEAK_GOLDEN_LINE, + barIndex, + maxRequiredBars, + peakGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VALE_GOLDEN_LINE, + barIndex, + maxRequiredBars, + valeGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L1_LINE, + barIndex, + maxRequiredBars, + fiboLevel1Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L2_LINE, + barIndex, + maxRequiredBars, + fiboLevel2Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L3_LINE, + barIndex, + maxRequiredBars, + fiboLevel3Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L4_LINE, + barIndex, + maxRequiredBars, + fiboLevel4Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L5_LINE, + barIndex, + maxRequiredBars, + fiboLevel5Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TREND_STATE_LINE, + barIndex, + maxRequiredBars, + trendStateBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + kiBuffer, + maxAllowed // + ); + + // + CleanupArray( + tkiBuffer, + maxAllowed // + ); + + // + CleanupArray( + vidyaBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + mahBuffer, + maxAllowed // + ); + + // + CleanupArray( + malBuffer, + maxAllowed // + ); + + // + CleanupArray( + macBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendBuffer, + maxAllowed // + ); + + // + CleanupArray( + kiStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + tkiStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + vidyaStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + supportBuffer, + maxAllowed // + ); + + // + CleanupArray( + swingLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + swingHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + resistanceBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel1Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel2Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel3Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel4Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel5Buffer, + maxAllowed // + ); + + // + CleanupArray( + trendStateBuffer, + maxAllowed // + ); + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 new file mode 100644 index 0000000..6bfab82 --- /dev/null +++ b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 @@ -0,0 +1,5548 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCatbHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_XCATB_BUFFERS +{ + X121_XCATB_SAR_LINE = 0, + X121_XCATB_SAR_STATE_LINE = 28, + X121_XCATB_PEAK_LINE = 2, + X121_XCATB_VALE_LINE = 3, + X121_XCATB_PEAK_GOLDEN_LINE = 4, + X121_XCATB_VALE_GOLDEN_LINE = 5, + X121_XCATB_ATR_BAND_UPPER_LINE = 6, + X121_XCATB_ATR_BAND_LOWER_LINE = 7, + X121_XCATB_TREND_LINE = 8, + X121_XCATB_TREND_STATE_LINE = 29, + X121_XCATB_SBAR_O_LINE = 10, + X121_XCATB_SBAR_H_LINE = 11, + X121_XCATB_SBAR_L_LINE = 12, + X121_XCATB_SBAR_C_LINE = 13, + X121_XCATB_HK_SBAR_O_LINE = 15, + X121_XCATB_HK_SBAR_H_LINE = 16, + X121_XCATB_HK_SBAR_L_LINE = 17, + X121_XCATB_HK_SBAR_C_LINE = 18, + X121_XCATB_S_HH_LINE = 20, + X121_XCATB_S_LL_LINE = 21, + X121_XCATB_M_HH_LINE = 22, + X121_XCATB_M_LL_LINE = 23, + X121_XCATB_L_HH_LINE = 24, + X121_XCATB_L_LL_LINE = 25, + X121_XCATB_H_HH_LINE = 26, + X121_XCATB_H_LL_LINE = 27, + X121_XCATB_RSI_LINE = 30, + X121_XCATB_ADX_LINE = 31, + X121_XCATB_ADXP_LINE = 32, + X121_XCATB_ADXN_LINE = 33, + X121_XCATB_DELTA_LINE = 34, + X121_XCATB_DELTA_SIGNAL_LINE = 35, + X121_XCATB_VOLUME_BULLISH_LINE = 36, + X121_XCATB_VOLUME_BEARISH_LINE = 37, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE = 38, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE = 39, + X121_XCATB_ATR_LINE = 40, + X121_XCATB_ATR_BAND_RAW_UPPER_LINE = 41, + X121_XCATB_ATR_BAND_RAW_LOWER_LINE = 42, + X121_XCATB_HK_BAR_O_LINE = 43, + X121_XCATB_HK_BAR_H_LINE = 44, + X121_XCATB_HK_BAR_L_LINE = 45, + X121_XCATB_HK_BAR_C_LINE = 46, +}; + +// +// Input Models ... +struct X121XCatbInputs +{ + // + // Props ... + + // + // Market ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Short Period + ENUM_TIMEFRAMES scPeriod; // Short Period + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Medium Period + ENUM_TIMEFRAMES mcPeriod; // Medium Period + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Long Period + ENUM_TIMEFRAMES lcPeriod; // Long Period + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Hind Period + ENUM_TIMEFRAMES hcPeriod; // Hind Period + ENUM_X_MARKET_CYCLES appliedCycle; // Applied Cycle + + // + // Signal ... + int signalR2R; // Risk Reward Ratio + bool drawSignals; // Draw Signal + bool drawTriggerBlock; // Draw Trigger Block + double slAtrMultiplier; // ATR Multiplier for SL + + // + // Validating ... + bool forceHasSwing; // Force Blocks to Have Swing + bool forceOBBarType; // Force Block Has Reversal Bar + bool forceOBFVGBarType; // Force FVG Has Same Bars + bool forceHasFLiquidity; // Force Blocks to Have Following Liquidity + bool forceHasRLiquidity; // Force Blocks to Have Reversal Liquidity + bool validateGapSequence; // Validate Block's Gap Sequence + bool validateBlockEdgeBreakout; // Validate Block's Edge Breakout + + // + // Filtering ... + bool filterBasedOnPV; // Filter Based on Peak and Vale + bool filterBasedOnSar; // Filter Based on Sar + bool filterBasedOnRSI; // Filter Based on RSI + bool filterBasedOnADX; // Filter Based on ADX + bool filterBasedOnATR; // Filter Based on ATR + bool filterBasedOnTrend; // Filter Based on Trend + bool filterBasedOnDelta; // Filter Based on Delta + bool filterBasedOnVolume; // Filter Based on Volume + bool filterBasedOnSignalBar; // Filter Based on Signal Bar + bool filterBasedOnHKSignalBar; // Filter Based on Hiken Ashi Signal Bar + + // + // Alert ... + string alertPrefix; // Alert Prefix + bool logAlerts; // Log Alerts + bool pushAlerts; // Push Alerts + bool mailAlerts; // Mail Alerts + bool terminalAlerts; // Terminal Alerts + + // + // Presentation ... + bool showBars; // Show Bars + bool showPV; // Show PV + bool showPVGolden; // Show PV Golden + bool showSar; // Show Sar + bool showTrend; // Show Trend + bool showATRBand; // Show ATR Band + bool showSignalBars; // Show Signal Bars + bool showHKSignalBars; // Show Hiken Ashi Signal Bars + + // + double rsiOBLevel; // RSI OB Level + double rsiOSLevel; // RSI OS Level + double adxThreshold; // ADX Threshold + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + // Constructor(s) ... + X121XCatbInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Signal ... + signalR2R = 0; // Risk Reward Ratio + drawSignals = false; // Draw Signal + drawTriggerBlock = false; // Draw Trigger Block + slAtrMultiplier = 0; // ATR Multiplier for SL + + // + // Validating ... + forceHasSwing = false; // Force Blocks to Have Swing + forceOBBarType = false; // Force Block Has Reversal Bar + forceOBFVGBarType = false; // Force FVG Has Same Bars + forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity + forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity + validateGapSequence = false; // Validate Block's Gap Sequence + validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + + // + // Filtering ... + filterBasedOnPV = false; // Filter Based on Peak and Vale + filterBasedOnSar = false; // Filter Based on Sar + filterBasedOnRSI = false; // Filter Based on RSI + filterBasedOnADX = false; // Filter Based on ADX + filterBasedOnATR = false; // Filter Based on ATR + filterBasedOnTrend = false; // Filter Based on Trend + filterBasedOnDelta = false; // Filter Based on Delta + filterBasedOnVolume = false; // Filter Based on Volume + filterBasedOnSignalBar = false; // Filter Based on Signal Bar + filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + + // + // Alert ... + alertPrefix = ""; // Alert Prefix + logAlerts = false; // Log Alerts + pushAlerts = false; // Push Alerts + mailAlerts = false; // Mail Alerts + terminalAlerts = false; // Terminal Alerts + + // + // Presentation ... + showBars = false; // Show Bars + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Signal ... + signalR2R = 4; // Risk Reward Ratio + drawSignals = false; // Draw Signal + drawTriggerBlock = false; // Draw Trigger Block + slAtrMultiplier = 1.0; // ATR Multiplier for SL + + // + // Validating ... + forceHasSwing = false; // Force Blocks to Have Swing + forceOBBarType = false; // Force Block Has Reversal Bar + forceOBFVGBarType = false; // Force FVG Has Same Bars + forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity + forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity + validateGapSequence = false; // Validate Block's Gap Sequence + validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + + // + // Filtering ... + filterBasedOnPV = false; // Filter Based on Peak and Vale + filterBasedOnSar = false; // Filter Based on Sar + filterBasedOnRSI = false; // Filter Based on RSI + filterBasedOnADX = false; // Filter Based on ADX + filterBasedOnATR = false; // Filter Based on ATR + filterBasedOnTrend = false; // Filter Based on Trend + filterBasedOnDelta = false; // Filter Based on Delta + filterBasedOnVolume = false; // Filter Based on Volume + filterBasedOnSignalBar = false; // Filter Based on Signal Bar + filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + + // + // Alert ... + alertPrefix = ""; // Alert Prefix + logAlerts = false; // Log Alerts + pushAlerts = false; // Push Alerts + mailAlerts = false; // Mail Alerts + terminalAlerts = false; // Terminal Alerts + + // + // Presentation ... + showBars = true; // Show Bars + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 1500; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showPV = false; + showPVGolden = false; + showSar = false; + showTrend = false; + showATRBand = false; + showSignalBars = false; + showHKSignalBars = false; + + // + drawSignals = false; + drawTriggerBlock = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(appliedCycle) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + return result; + } + + // +}; + +// +// Conditions ... +struct X121XCatbConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + double rsiOBLevel; // Over Bought Level + double rsiOSLevel; // Over Sold Level + double adxThreshold; // Big Movement Threshold + + // + // Conditions ... + + // + // ATR Band ... + + // + bool isATRUp; + bool isATRDown; + + // + bool isClosedOverATRUpper; + bool isClosedUnderATRLower; + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + // ADX ... + + // + bool isADXBiggerLast; + bool isADXLesserLast; + + // + bool isADXOverThreshold; + bool isADXUnderThreshold; + + // + bool isDXPBiggerThanDXN; + bool isDXNBiggerThanDXP; + + // + bool isADXBullish; + bool isADXBearish; + + // + bool isADXSwitchedToBullish; + bool isADXSwitchedToBearish; + + // + // RSI ... + + // + bool isRSIBullish; + bool isRSIBearish; + + // + bool isRSISwitchedToBullish; + bool isRSISwitchedToBearish; + + // + bool isRSIOB; + bool isRSIOS; + + // + bool isRSICrossedOverOB; + bool isRSICrossedOverOS; + + // + bool isRSICrossedUnderOB; + bool isRSICrossedUnderOS; + + // + // DELTA ... + + // + bool isDeltaUp; + bool isDeltaDown; + + // + bool isDeltaBullish; + bool isDeltaBearish; + + // + bool isDeltaSwitchedToBullish; + bool isDeltaSwitchedToBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish; + bool isVolumeBearish; + + // + bool isVolumeSwitchedToBullish; + bool isVolumeSwitchedToBearish; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish; + bool isSBarBearish; + + // + bool isSBarSwitchedToBullish; + bool isSBarSwitchedToBearish; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish; + bool isHKSBarBearish; + + // + bool isHKSBarSwitchedToBullish; + bool isHKSBarSwitchedToBearish; + + // + // TREND ... + + // + bool isTrendUp; + bool isTrendDown; + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + // PEAK ... + + // + bool isPeakSameLast; + bool isPeakOverLast; + bool isPeakUnderLast; + + // + // VALE ... + + // + bool isValeSameLast; + bool isValeOverLast; + bool isValeUnderLast; + + // + // Constructor ... + X121XCatbConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + Clean(bars); + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + + // + ArraySetAsSeries(bars, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + rsiOBLevel = 0; // Over Bought Level + rsiOSLevel = 0; // Over Sold Level + adxThreshold = 0; // Big Movement Threshold + + // + // Conditions ... + + // + // Conditions ... + + // + // ATR Band ... + + // + isATRUp = false; + isATRDown = false; + + // + isClosedOverATRUpper = false; + isClosedUnderATRLower = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // ADX ... + + // + isADXBiggerLast = false; + isADXLesserLast = false; + + // + isADXOverThreshold = false; + isADXUnderThreshold = false; + + // + isDXPBiggerThanDXN = false; + isDXNBiggerThanDXP = false; + + // + isADXBullish = false; + isADXBearish = false; + + // + isADXSwitchedToBullish = false; + isADXSwitchedToBearish = false; + + // + // RSI ... + + // + isRSIBullish = false; + isRSIBearish = false; + + // + isRSISwitchedToBullish = false; + isRSISwitchedToBearish = false; + + // + isRSIOB = false; + isRSIOS = false; + + // + isRSICrossedOverOB = false; + isRSICrossedOverOS = false; + + // + isRSICrossedUnderOB = false; + isRSICrossedUnderOS = false; + + // + // DELTA ... + + // + isDeltaUp = false; + isDeltaDown = false; + + // + isDeltaBullish = false; + isDeltaBearish = false; + + // + isDeltaSwitchedToBullish = false; + isDeltaSwitchedToBearish = false; + + // + // VOLUME ... + + // + isVolumeBullish = false; + isVolumeBearish = false; + + // + isVolumeSwitchedToBullish = false; + isVolumeSwitchedToBearish = false; + // + // SIGNAL Bar ... + + // + isSBarBullish = false; + isSBarBearish = false; + + // + isSBarSwitchedToBullish = false; + isSBarSwitchedToBearish = false; + + // + // XHK Signal Bar ... + + // + isHKSBarBullish = false; + isHKSBarBearish = false; + + // + isHKSBarSwitchedToBullish = false; + isHKSBarSwitchedToBearish = false; + + // + // TREND ... + + // + isTrendUp = false; + isTrendDown = false; + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + // PEAK ... + + // + isPeakSameLast = false; + isPeakOverLast = false; + isPeakUnderLast = false; + + // + // VALE ... + + // + isValeSameLast = false; + isValeOverLast = false; + isValeUnderLast = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // ATR Band ... + + // + if (isATRUp) + { + bullishScore += score; + } + if (isClosedOverATRUpper) + { + bullishScore += score; + } + + // + if (isATRDown) + { + bearishScore += score; + } + if (isClosedUnderATRLower) + { + bearishScore += score; + } + + // + // SAR ... + + // + if (isSarBullish) + { + bullishScore += score; + } + if (isSarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSarBearish) + { + bearishScore += score; + } + if (isSarSwitchedToBearish) + { + bearishScore += score; + } + + // + // ADX ... + + // + if (isADXBullish) + { + bullishScore += score; + } + if (isADXBiggerLast) + { + bullishScore += score; + } + if (isDXPBiggerThanDXN) + { + bullishScore += score; + } + if (isADXOverThreshold) + { + bullishScore += score; + } + if (isADXSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isADXBearish) + { + bearishScore += score; + } + if (isADXLesserLast) + { + bearishScore += score; + } + if (isDXNBiggerThanDXP) + { + bearishScore += score; + } + if (isADXUnderThreshold) + { + bearishScore += score; + } + if (isADXSwitchedToBearish) + { + bearishScore += score; + } + + // + // RSI ... + + // + if (isRSIOS) + { + bullishScore += score; + } + if (isRSIBullish) + { + bullishScore += score; + } + if (isRSICrossedOverOS) + { + bullishScore += score; + } + if (isRSICrossedOverOB) + { + bullishScore += score; + } + if (isRSISwitchedToBullish) + { + bullishScore += score; + } + + // + if (isRSIOB) + { + bearishScore += score; + } + if (isRSIBearish) + { + bearishScore += score; + } + if (isRSICrossedUnderOB) + { + bearishScore += score; + } + if (isRSICrossedUnderOS) + { + bearishScore += score; + } + if (isRSISwitchedToBearish) + { + bearishScore += score; + } + + // + // DELTA ... + + // + if (isDeltaUp) + { + bullishScore += score; + } + if (isDeltaBullish) + { + bullishScore += score; + } + if (isDeltaSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isDeltaDown) + { + bearishScore += score; + } + if (isDeltaBearish) + { + bearishScore += score; + } + if (isDeltaSwitchedToBearish) + { + bearishScore += score; + } + + // + // VOLUME ... + + // + if (isVolumeBullish) + { + bullishScore += score; + } + if (isVolumeSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isVolumeBearish) + { + bearishScore += score; + } + if (isVolumeSwitchedToBearish) + { + bearishScore += score; + } + + // + // SIGNAL Bar ... + + // + if (isSBarBullish) + { + bullishScore += score; + } + if (isSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSBarBearish) + { + bearishScore += score; + } + if (isSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // XHK Signal Bar ... + + // + if (isHKSBarBullish) + { + bullishScore += score; + } + if (isHKSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isHKSBarBearish) + { + bearishScore += score; + } + if (isHKSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // TREND ... + + // + if (isTrendUp) + { + bullishScore += score; + } + if (isTrendBullish) + { + bullishScore += score; + } + if (isTrendSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isTrendDown) + { + bearishScore += score; + } + if (isTrendBearish) + { + bearishScore += score; + } + if (isTrendSwitchedToBearish) + { + bearishScore += score; + } + + // + // PEAK and VALE ... + + // + if (isValeSameLast) + { + bullishScore += score; + } + if (isValeOverLast) + { + bullishScore += score; + } + if (isPeakOverLast) + { + bullishScore += score; + } + + // + if (isPeakSameLast) + { + bearishScore += score; + } + if (isPeakUnderLast) + { + bearishScore += score; + } + if (isValeUnderLast) + { + bearishScore += score; + } + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XCATB: " + separator + + "-----------------------" + separator + + "" + separator + + // + "-----------------------" + separator + + "ATR Band: " + separator + + "-----------------------" + separator + + ToString("isATRUp", isATRUp, ignoreFalseConditions, separator) + + ToString("isATRDown", isATRDown, ignoreFalseConditions, separator) + + ToString("isClosedOverATRUpper", isClosedOverATRUpper, ignoreFalseConditions, separator) + + ToString("isClosedUnderATRLower", isClosedUnderATRLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SAR: " + separator + + "-----------------------" + separator + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "ADX: " + separator + + "-----------------------" + separator + + ToString("isADXBiggerLast", isADXBiggerLast, ignoreFalseConditions, separator) + + ToString("isADXLesserLast", isADXLesserLast, ignoreFalseConditions, separator) + + ToString("isADXOverThreshold", isADXOverThreshold, ignoreFalseConditions, separator) + + ToString("isADXUnderThreshold", isADXUnderThreshold, ignoreFalseConditions, separator) + + ToString("isDXPBiggerThanDXN", isDXPBiggerThanDXN, ignoreFalseConditions, separator) + + ToString("isDXNBiggerThanDXP", isDXNBiggerThanDXP, ignoreFalseConditions, separator) + + ToString("isADXBullish", isADXBullish, ignoreFalseConditions, separator) + + ToString("isADXBearish", isADXBearish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBullish", isADXSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBearish", isADXSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "RSI: " + separator + + "-----------------------" + separator + + ToString("isRSIBullish", isRSIBullish, ignoreFalseConditions, separator) + + ToString("isRSIBearish", isRSIBearish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBullish", isRSISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBearish", isRSISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRSIOB", isRSIOB, ignoreFalseConditions, separator) + + ToString("isRSIOS", isRSIOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOB", isRSICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOS", isRSICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOB", isRSICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOS", isRSICrossedUnderOS, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "DELTA: " + separator + + "-----------------------" + separator + + ToString("isDeltaUp", isDeltaUp, ignoreFalseConditions, separator) + + ToString("isDeltaDown", isDeltaDown, ignoreFalseConditions, separator) + + ToString("isDeltaBullish", isDeltaBullish, ignoreFalseConditions, separator) + + ToString("isDeltaBearish", isDeltaBearish, ignoreFalseConditions, separator) + + ToString("isDeltaSwitchedToBullish", isDeltaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isDeltaSwitchedToBearish", isDeltaSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "VOLUME: " + separator + + "-----------------------" + separator + + ToString("isVolumeBullish", isVolumeBullish, ignoreFalseConditions, separator) + + ToString("isVolumeBearish", isVolumeBearish, ignoreFalseConditions, separator) + + ToString("isVolumeSwitchedToBullish", isVolumeSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isVolumeSwitchedToBearish", isVolumeSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SIGNAL Bar: " + separator + + "-----------------------" + separator + + ToString("isSBarBullish", isSBarBullish, ignoreFalseConditions, separator) + + ToString("isSBarBearish", isSBarBearish, ignoreFalseConditions, separator) + + ToString("isSBarSwitchedToBullish", isSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSBarSwitchedToBearish", isSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "XHK Signal Bar: " + separator + + "-----------------------" + separator + + ToString("isHKSBarBullish", isHKSBarBullish, ignoreFalseConditions, separator) + + ToString("isHKSBarBearish", isHKSBarBearish, ignoreFalseConditions, separator) + + ToString("isHKSBarSwitchedToBullish", isHKSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHKSBarSwitchedToBearish", isHKSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Trend: " + separator + + "-----------------------" + separator + + ToString("isTrendUp", isTrendUp, ignoreFalseConditions, separator) + + ToString("isTrendDown", isTrendDown, ignoreFalseConditions, separator) + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Peak: " + separator + + "-----------------------" + separator + + ToString("isPeakSameLast", isPeakSameLast, ignoreFalseConditions, separator) + + ToString("isPeakOverLast", isPeakOverLast, ignoreFalseConditions, separator) + + ToString("isPeakUnderLast", isPeakUnderLast, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Vale: " + separator + + "-----------------------" + separator + + ToString("isValeSameLast", isValeSameLast, ignoreFalseConditions, separator) + + ToString("isValeOverLast", isValeOverLast, ignoreFalseConditions, separator) + + ToString("isValeUnderLast", isValeUnderLast, ignoreFalseConditions, separator) + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCatbHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Buffers ... + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + // Market Shift ... + + // + // SAR ... + XDirectionShift lastSarBullish; + XDirectionShift lastSarBearish; + + // + // TREND ... + XDirectionShift lastTrendBullish; + XDirectionShift lastTrendBearish; + + // + // DELTA ... + XDirectionShift lastDeltaBullish; + XDirectionShift lastDeltaBearish; + + // + // VOLUME ... + XDirectionShift lastVolumeBullish; + XDirectionShift lastVolumeBearish; + + // + // SIGNAL Bar ... + XDirectionShift lastSignalBarBullish; + XDirectionShift lastSignalBarBearish; + + // + // XHK SIGNAL Bar ... + XDirectionShift lastHKSignalBarBullish; + XDirectionShift lastHKSignalBarBearish; + + // + // Constructors ... + XCX121XCatbHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCatbHelper() + { + // + mInputs.Clean(); + + // + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCatbInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcatb", + "", // Market ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.appliedCycle, + "", // Signal ... + mInputs.signalR2R, + mInputs.drawSignals, + mInputs.drawTriggerBlock, + mInputs.slAtrMultiplier, + "", // Validating ... + mInputs.forceHasSwing, + mInputs.forceOBBarType, + mInputs.forceOBFVGBarType, + mInputs.forceHasFLiquidity, + mInputs.forceHasRLiquidity, + mInputs.validateGapSequence, + mInputs.validateBlockEdgeBreakout, + "", // Filtering ... + mInputs.filterBasedOnPV, + mInputs.filterBasedOnSar, + mInputs.filterBasedOnRSI, + mInputs.filterBasedOnADX, + mInputs.filterBasedOnATR, + mInputs.filterBasedOnTrend, + mInputs.filterBasedOnDelta, + mInputs.filterBasedOnVolume, + mInputs.filterBasedOnSignalBar, + mInputs.filterBasedOnHKSignalBar, + "", // Alerts ... + mInputs.alertPrefix, + mInputs.logAlerts, + mInputs.pushAlerts, + mInputs.mailAlerts, + mInputs.terminalAlerts, + "", // Presentation ... + mInputs.showBars, + mInputs.showPV, + mInputs.showPVGolden, + mInputs.showSar, + mInputs.showTrend, + mInputs.showATRBand, + mInputs.showSignalBars, + mInputs.showHKSignalBars, + mInputs.startCalculationForLastBars + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + void Check(int barIndex = 0) + { + // + bool has = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + X121XCatbConditions conditions; + has = GetConditions( + conditions, + barIndex, + 4 // + ); + if (!has) + { + // + conditions.Clean(); + return; + } + + // + // Checking Shifts ... + + // + // SAR ... + + // + isBullish = conditions.isSarSwitchedToBullish; + isBearish = conditions.isSarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSarBullish.IsValid() + ? true + : lastSarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBullish.Clean(); + + // + lastSarBullish.type = "SAR"; + lastSarBullish.symbol = conditions.symbol; + lastSarBullish.period = conditions.period; + lastSarBullish.at = conditions.bars[1].time; + lastSarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSarBullish.after = conditions.sarBuffer[1]; + lastSarBullish.before = conditions.sarBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSarBearish.IsValid() + ? true + : lastSarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBearish.Clean(); + + // + lastSarBearish.type = "SAR"; + lastSarBearish.symbol = conditions.symbol; + lastSarBearish.period = conditions.period; + lastSarBearish.at = conditions.bars[1].time; + lastSarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSarBearish.after = conditions.sarBuffer[1]; + lastSarBearish.before = conditions.sarBuffer[2]; + } + } + + // + // TREND ... + + // + isBullish = conditions.isTrendSwitchedToBullish; + isBearish = conditions.isTrendSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastTrendBullish.IsValid() + ? true + : lastTrendBullish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBullish.Clean(); + + // + lastTrendBullish.type = "TREND"; + lastTrendBullish.symbol = conditions.symbol; + lastTrendBullish.period = conditions.period; + lastTrendBullish.at = conditions.bars[1].time; + lastTrendBullish.shiftTo = X_DIRECTION_BULLISH; + lastTrendBullish.after = conditions.trendBuffer[1]; + lastTrendBullish.before = conditions.trendBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastTrendBearish.IsValid() + ? true + : lastTrendBearish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBearish.Clean(); + + // + lastTrendBearish.type = "TREND"; + lastTrendBearish.symbol = conditions.symbol; + lastTrendBearish.period = conditions.period; + lastTrendBearish.at = conditions.bars[1].time; + lastTrendBearish.shiftTo = X_DIRECTION_BEARISH; + lastTrendBearish.after = conditions.trendBuffer[1]; + lastTrendBearish.before = conditions.trendBuffer[2]; + } + } + + // + // DELTA ... + + // + isBullish = + // + ( + // + // Delta is Up ... + conditions.deltaBuffer[1] > conditions.deltaBuffer[2] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[1] > conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Over Delta ... + conditions.deltaBuffer[1] > conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] <= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + isBearish = + // + ( + // + // Delta is Down ... + conditions.deltaBuffer[1] < conditions.deltaBuffer[2] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[1] < conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[1] < conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] >= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastDeltaBullish.IsValid() + ? true + : lastDeltaBullish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBullish.Clean(); + + // + lastDeltaBullish.type = "DELTA"; + lastDeltaBullish.symbol = conditions.symbol; + lastDeltaBullish.period = conditions.period; + lastDeltaBullish.at = conditions.bars[1].time; + lastDeltaBullish.shiftTo = X_DIRECTION_BULLISH; + lastDeltaBullish.after = conditions.bars[1].close; + lastDeltaBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastDeltaBearish.IsValid() + ? true + : lastDeltaBearish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBearish.Clean(); + + // + lastDeltaBearish.type = "DELTA"; + lastDeltaBearish.symbol = conditions.symbol; + lastDeltaBearish.period = conditions.period; + lastDeltaBearish.at = conditions.bars[1].time; + lastDeltaBearish.shiftTo = X_DIRECTION_BEARISH; + lastDeltaBearish.after = conditions.bars[1].close; + lastDeltaBearish.before = conditions.bars[2].close; + } + } + + // + // VOLUME ... + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] && + conditions.bullishVolumeSignalBuffer[2] <= conditions.bearishVolumeSignalBuffer[2] + // + ) + // + ; + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] && + conditions.bearishVolumeSignalBuffer[2] <= conditions.bullishVolumeSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastVolumeBullish.IsValid() + ? true + : lastVolumeBullish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBullish.Clean(); + + // + lastVolumeBullish.type = "VOLUME"; + lastVolumeBullish.symbol = conditions.symbol; + lastVolumeBullish.period = conditions.period; + lastVolumeBullish.at = conditions.bars[1].time; + lastVolumeBullish.shiftTo = X_DIRECTION_BULLISH; + lastVolumeBullish.after = conditions.bars[1].close; + lastVolumeBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastVolumeBearish.IsValid() + ? true + : lastVolumeBearish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBearish.Clean(); + + // + lastVolumeBearish.type = "VOLUME"; + lastVolumeBearish.symbol = conditions.symbol; + lastVolumeBearish.period = conditions.period; + lastVolumeBearish.at = conditions.bars[1].time; + lastVolumeBearish.shiftTo = X_DIRECTION_BEARISH; + lastVolumeBearish.after = conditions.bars[1].close; + lastVolumeBearish.before = conditions.bars[2].close; + } + } + + // + // SIGNAL Bar ... + + // + isBullish = conditions.isSBarSwitchedToBullish; + isBearish = conditions.isSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSignalBarBullish.IsValid() + ? true + : lastSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBullish.Clean(); + + // + lastSignalBarBullish.type = "SIGNALBAR"; + lastSignalBarBullish.symbol = conditions.symbol; + lastSignalBarBullish.period = conditions.period; + lastSignalBarBullish.at = conditions.bars[1].time; + lastSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSignalBarBullish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBullish.before = conditions.sBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSignalBarBearish.IsValid() + ? true + : lastSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBearish.Clean(); + + // + lastSignalBarBearish.type = "SIGNALBAR"; + lastSignalBarBearish.symbol = conditions.symbol; + lastSignalBarBearish.period = conditions.period; + lastSignalBarBearish.at = conditions.bars[1].time; + lastSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSignalBarBearish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBearish.before = conditions.sBarCloseBuffer[2]; + } + } + + // + // HKSIGNAL Bar ... + + // + isBullish = conditions.isHKSBarSwitchedToBullish; + isBearish = conditions.isHKSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastHKSignalBarBullish.IsValid() + ? true + : lastHKSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBullish.Clean(); + + // + lastHKSignalBarBullish.type = "HKSIGNALBAR"; + lastHKSignalBarBullish.symbol = conditions.symbol; + lastHKSignalBarBullish.period = conditions.period; + lastHKSignalBarBullish.at = conditions.bars[1].time; + lastHKSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastHKSignalBarBullish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBullish.before = conditions.hkSBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastHKSignalBarBearish.IsValid() + ? true + : lastHKSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBearish.Clean(); + + // + lastHKSignalBarBearish.type = "HKSIGNALBAR"; + lastHKSignalBarBearish.symbol = conditions.symbol; + lastHKSignalBarBearish.period = conditions.period; + lastHKSignalBarBearish.at = conditions.bars[1].time; + lastHKSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastHKSignalBarBearish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBearish.before = conditions.hkSBarCloseBuffer[2]; + } + } + + // + // Cleanup Resources ... + + // + conditions.Clean(); + } + + // + // Inputs ... + + // + X121XCatbInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCatbInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarStateBuffer[barIndex]; + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarStateBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK Golden ... + + // + double GetPeakGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakGoldenBuffer[barIndex]; + } + + // + int CopyPeakGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE Golden ... + + // + double GetValeGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeGoldenBuffer[barIndex]; + } + + // + int CopyValeGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Upper ... + + // + double GetATRUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrUpperBuffer[barIndex]; + } + + // + int CopyATRUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Lower ... + + // + double GetATRLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrLowerBuffer[barIndex]; + } + + // + int CopyATRLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendBuffer[barIndex]; + } + + // + int CopyTrend( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND State ... + + // + double GetTrendState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendStateBuffer[barIndex]; + } + + // + int CopyTrendState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SIGNAL Bar ... + + // + // OPEN ... + + // + double GetSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarOpenBuffer[barIndex]; + } + + // + int CopySBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarCloseBuffer[barIndex]; + } + + // + int CopySBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK SIGNAL Bar ... + + // + // OPEN ... + + // + double GetHKSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarOpenBuffer[barIndex]; + } + + // + int CopyHKSBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetHKSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarCloseBuffer[barIndex]; + } + + // + int CopyHKSBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXP ... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxpBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxpBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXN ... + + // + double GetADXN( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxnBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxnBuffer[barIndex]; + } + + // + int CopyADXN( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxnBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA ... + + // + double GetDelta( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaBuffer[barIndex]; + } + + // + int CopyDelta( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA Signal ... + + // + double GetDeltaSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaSignalBuffer[barIndex]; + } + + // + int CopyDeltaSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME ... + + // + // Bullish ... + + // + double GetBullishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeBuffer[barIndex]; + } + + // + int CopyBullishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeBuffer[barIndex]; + } + + // + int CopyBearishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME Signal ... + + // + // Bullish ... + + // + double GetBullishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBullishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBearishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK ... + + // + // Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkOpenBuffer[barIndex]; + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkHighBuffer[barIndex]; + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkHighBuffer, + buffer, + forceClean + // + ); + } + + // + // Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkLowBuffer[barIndex]; + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkLowBuffer, + buffer, + forceClean + // + ); + } + + // + // Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkCloseBuffer[barIndex]; + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + int CopyRSI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // Tools ... + + // + void Update( + int barIndex // Bar Index + ) + { + // + Calculate(barIndex); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCatbConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + // Filling Bars ... + int barsCount = GetBars( + conditions.bars, + mSymbol, + mPeriod, + barIndex, + loopback // + ); + result = barsCount == loopback; + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // + // Buffers ... + + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyPeakGolden( + zIndex, + loopback, + conditions.peakGoldenBuffer // + ); + + // + CopyValeGolden( + zIndex, + loopback, + conditions.valeGoldenBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyATRUpper( + zIndex, + loopback, + conditions.atrUpperBuffer // + ); + + // + CopyATRLower( + zIndex, + loopback, + conditions.atrLowerBuffer // + ); + + // + CopyTrend( + zIndex, + loopback, + conditions.trendBuffer // + ); + + // + CopyTrendState( + zIndex, + loopback, + conditions.trendStateBuffer // + ); + + // + CopySBarOpen( + zIndex, + loopback, + conditions.sBarOpenBuffer // + ); + + // + CopySBarClose( + zIndex, + loopback, + conditions.sBarCloseBuffer // + ); + + // + CopyHKSBarOpen( + zIndex, + loopback, + conditions.hkSBarOpenBuffer // + ); + + // + CopyHKSBarClose( + zIndex, + loopback, + conditions.hkSBarCloseBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxpBuffer // + ); + + // + CopyADXN( + zIndex, + loopback, + conditions.adxnBuffer // + ); + + // + CopyDelta( + zIndex, + loopback, + conditions.deltaBuffer // + ); + + // + CopyDeltaSignal( + zIndex, + loopback, + conditions.deltaSignalBuffer // + ); + + // + CopyBullishVolume( + zIndex, + loopback, + conditions.bullishVolumeBuffer // + ); + + // + CopyBearishVolume( + zIndex, + loopback, + conditions.bearishVolumeBuffer // + ); + + // + CopyBullishVolumeSignal( + zIndex, + loopback, + conditions.bullishVolumeSignalBuffer // + ); + + // + CopyBearishVolumeSignal( + zIndex, + loopback, + conditions.bearishVolumeSignalBuffer // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + // Calculate ... + + // + double _rsiOBLevel = mInputs.rsiOBLevel; // Over Bought Level + double _rsiOSLevel = mInputs.rsiOSLevel; // Over Sold Level + double _adxThreshold = mInputs.adxThreshold; // Big Movement Threshold + + // + // Reading Values ... + + // + // ATR Upper ... + double zATRUpper = conditions.atrUpperBuffer[zIDX]; + double cATRUpper = conditions.atrUpperBuffer[cIDX]; + double pATRUpper = conditions.atrUpperBuffer[pIDX]; + double p2ATRUpper = conditions.atrUpperBuffer[p2IDX]; + double p3ATRUpper = conditions.atrUpperBuffer[p3IDX]; + + // + // ATR Lower ... + double zATRLower = conditions.atrLowerBuffer[zIDX]; + double cATRLower = conditions.atrLowerBuffer[cIDX]; + double pATRLower = conditions.atrLowerBuffer[pIDX]; + double p2ATRLower = conditions.atrLowerBuffer[p2IDX]; + double p3ATRLower = conditions.atrLowerBuffer[p3IDX]; + + // + // SAR ... + + // + double zSAR = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSAR = conditions.sarBuffer[pIDX]; + double p2SAR = conditions.sarBuffer[p2IDX]; + double p3SAR = conditions.sarBuffer[p3IDX]; + + // + double zSarState = conditions.sarStateBuffer[zIDX]; + double cSarState = conditions.sarStateBuffer[cIDX]; + double pSarState = conditions.sarStateBuffer[pIDX]; + double p2SarState = conditions.sarStateBuffer[p2IDX]; + double p3SarState = conditions.sarStateBuffer[p3IDX]; + + // + // ADX ... + + // + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + double p3ADX = conditions.adxBuffer[p3IDX]; + + // + // ADX P ... + + // + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + double p3ADXP = conditions.adxpBuffer[p3IDX]; + + // + // ADX N ... + + // + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + double p3ADXN = conditions.adxnBuffer[p3IDX]; + + // + // RSI ... + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + double p3RSI = conditions.rsiBuffer[p3IDX]; + + // + // SIGNAL Bar ... + + // + double zSBarO = conditions.sBarOpenBuffer[zIDX]; + double cSBarO = conditions.sBarOpenBuffer[cIDX]; + double pSBarO = conditions.sBarOpenBuffer[pIDX]; + double p2SBarO = conditions.sBarOpenBuffer[p2IDX]; + double p3SBarO = conditions.sBarOpenBuffer[p3IDX]; + + // + double zSBarC = conditions.sBarCloseBuffer[zIDX]; + double cSBarC = conditions.sBarCloseBuffer[cIDX]; + double pSBarC = conditions.sBarCloseBuffer[pIDX]; + double p2SBarC = conditions.sBarCloseBuffer[p2IDX]; + double p3SBarC = conditions.sBarCloseBuffer[p3IDX]; + + // + // XHK SIGNAL Bar ... + + // + double zHKSBarO = conditions.hkSBarOpenBuffer[zIDX]; + double cHKSBarO = conditions.hkSBarOpenBuffer[cIDX]; + double pHKSBarO = conditions.hkSBarOpenBuffer[pIDX]; + double p2HKSBarO = conditions.hkSBarOpenBuffer[p2IDX]; + double p3HKSBarO = conditions.hkSBarOpenBuffer[p3IDX]; + + // + double zHKSBarC = conditions.hkSBarCloseBuffer[zIDX]; + double cHKSBarC = conditions.hkSBarCloseBuffer[cIDX]; + double pHKSBarC = conditions.hkSBarCloseBuffer[pIDX]; + double p2HKSBarC = conditions.hkSBarCloseBuffer[p2IDX]; + double p3HKSBarC = conditions.hkSBarCloseBuffer[p3IDX]; + + // + // TREND ... + + // + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + double p3Trend = conditions.trendBuffer[p3IDX]; + + // + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + double p3TrendState = conditions.trendStateBuffer[p3IDX]; + + // + // XPV ... + + // + double zPEAK = conditions.peakBuffer[zIDX]; + double cPEAK = conditions.peakBuffer[cIDX]; + double pPEAK = conditions.peakBuffer[pIDX]; + double p2PEAK = conditions.peakBuffer[p2IDX]; + double p3PEAK = conditions.peakBuffer[p3IDX]; + + // + double zVALE = conditions.valeBuffer[zIDX]; + double cVALE = conditions.valeBuffer[cIDX]; + double pVALE = conditions.valeBuffer[pIDX]; + double p2VALE = conditions.valeBuffer[p2IDX]; + double p3VALE = conditions.valeBuffer[p3IDX]; + + // + // DELTA ... + + // + double zDelta = conditions.deltaBuffer[zIDX]; + double cDelta = conditions.deltaBuffer[cIDX]; + double pDelta = conditions.deltaBuffer[pIDX]; + double p2Delta = conditions.deltaBuffer[p2IDX]; + double p3Delta = conditions.deltaBuffer[p3IDX]; + + // + double zDeltaSignal = conditions.deltaSignalBuffer[zIDX]; + double cDeltaSignal = conditions.deltaSignalBuffer[cIDX]; + double pDeltaSignal = conditions.deltaSignalBuffer[pIDX]; + double p2DeltaSignal = conditions.deltaSignalBuffer[p2IDX]; + double p3DeltaSignal = conditions.deltaSignalBuffer[p3IDX]; + + // + // VOLUME ... + + // + double zBullishVolume = conditions.bullishVolumeBuffer[zIDX]; + double cBullishVolume = conditions.bullishVolumeBuffer[cIDX]; + double pBullishVolume = conditions.bullishVolumeBuffer[pIDX]; + double p2BullishVolume = conditions.bullishVolumeBuffer[p2IDX]; + double p3BullishVolume = conditions.bullishVolumeBuffer[p3IDX]; + + // + double zBearishVolume = conditions.bearishVolumeBuffer[zIDX]; + double cBearishVolume = conditions.bearishVolumeBuffer[cIDX]; + double pBearishVolume = conditions.bearishVolumeBuffer[pIDX]; + double p2BearishVolume = conditions.bearishVolumeBuffer[p2IDX]; + double p3BearishVolume = conditions.bearishVolumeBuffer[p3IDX]; + + // + double zBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[zIDX]; + double cBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[cIDX]; + double pBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[pIDX]; + double p2BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p2IDX]; + double p3BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p3IDX]; + + // + double zBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[zIDX]; + double cBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[cIDX]; + double pBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[pIDX]; + double p2BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p2IDX]; + double p3BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p3IDX]; + + // + // ATR Band ... + + // + bool isATRUp = + cATRUpper > pATRUpper && + cATRLower > pATRLower; + bool isATRDown = + cATRUpper < pATRUpper && + cATRLower < pATRLower; + + // + bool isClosedOverATRUpper = + conditions.bars[cIDX].close > cATRUpper; + bool isClosedUnderATRLower = + conditions.bars[cIDX].close < cATRLower; + + // + // SAR ... + + // + bool isSarBullish = cSarState > 0; + bool isSarBearish = cSarState < 0; + + // + bool isSarSwitchedToBullish = + cSarState > 0 && + pSarState <= 0; + bool isSarSwitchedToBearish = + cSarState < 0 && + pSarState >= 0; + + // + // ADX ... + + // + bool isADXBiggerLast = + cADX > pADX; + bool isADXLesserLast = + cADX < pADX; + + // + bool isPADXBiggerLast = + pADX > p2ADX; + bool isPADXLesserLast = + pADX < p2ADX; + + // + bool isADXOverThreshold = + cADX > _adxThreshold; + bool isADXUnderThreshold = + cADX < _adxThreshold; + + // + bool isPADXOverThreshold = + pADX > _adxThreshold; + bool isPADXUnderThreshold = + pADX < _adxThreshold; + + // + bool isDXPBiggerThanDXN = + cADXP > cADXN; + bool isDXNBiggerThanDXP = + cADXN > cADXP; + + // + bool isPDXPBiggerThanDXN = + pADXP > pADXN; + bool isPDXNBiggerThanDXP = + pADXN > pADXP; + + // + bool isADXBullish = + isADXBiggerLast && + isADXOverThreshold; + bool isADXBearish = + isADXLesserLast && + isADXUnderThreshold; + + // + bool isPADXBullish = + isPADXBiggerLast && + isPADXOverThreshold; + bool isPADXBearish = + isPADXLesserLast && + isPADXUnderThreshold; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + // RSI ... + + // + bool isRSIBullish = + cRSI > pRSI; + bool isRSIBearish = + cRSI < pRSI; + + // + bool isRSISwitchedToBullish = + cRSI > pRSI && + pRSI <= cRSI; + bool isRSISwitchedToBearish = + cRSI < pRSI && + pRSI >= cRSI; + + // + bool isRSIOB = + cRSI > _rsiOBLevel; + bool isRSIOS = + cRSI < _rsiOSLevel; + + // + bool isRSICrossedOverOB = + cRSI > _rsiOBLevel && + pRSI <= _rsiOBLevel; + bool isRSICrossedOverOS = + cRSI > _rsiOSLevel && + pRSI <= _rsiOSLevel; + + // + bool isRSICrossedUnderOB = + cRSI < _rsiOBLevel && + pRSI >= _rsiOBLevel; + bool isRSICrossedUnderOS = + cRSI < _rsiOSLevel && + pRSI >= _rsiOSLevel; + + // + // DELTA ... + + // + bool isDeltaUp = + cDelta > pDelta; + bool isDeltaDown = + cDelta < pDelta; + + // + bool isDeltaBullish = + cDelta > pDelta && + cDeltaSignal > cDelta && + cDeltaSignal > pDeltaSignal; + bool isPDeltaBullish = + pDelta > p2Delta && + pDeltaSignal > pDelta && + pDeltaSignal > p2DeltaSignal; + + // + bool isDeltaBearish = + cDelta < pDelta && + cDeltaSignal < cDelta && + cDeltaSignal < pDeltaSignal; + bool isPDeltaBearish = + pDelta < p2Delta && + pDeltaSignal < pDelta && + pDeltaSignal < p2DeltaSignal; + + // + bool isDeltaSwitchedToBullish = + isDeltaBullish && + !isPDeltaBullish; + bool isDeltaSwitchedToBearish = + isDeltaBearish && + !isPDeltaBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish = + cBullishVolume > pBullishVolume && + cBullishVolume > cBearishVolume; + bool isVolumeBearish = + cBearishVolume > pBearishVolume && + cBearishVolume > cBullishVolume; + + // + bool isVolumeSwitchedToBullish = + isVolumeBullish && + cBullishVolumeSignal > cBearishVolumeSignal && + pBullishVolumeSignal <= pBearishVolumeSignal; + bool isVolumeSwitchedToBearish = + isVolumeBearish && + cBearishVolumeSignal > cBullishVolumeSignal && + pBearishVolumeSignal <= pBullishVolumeSignal; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish = + cSBarO < cSBarC; + bool isSBarBearish = + cSBarO > cSBarC; + + // + bool isSBarSwitchedToBullish = + cSBarO < cSBarC && + pSBarO >= pSBarC; + bool isSBarSwitchedToBearish = + cSBarO > cSBarC && + pSBarO <= pSBarC; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish = + cHKSBarO < cHKSBarC; + bool isHKSBarBearish = + cHKSBarO > cHKSBarC; + + // + bool isHKSBarSwitchedToBullish = + cHKSBarO < cHKSBarC && + pHKSBarO >= pHKSBarC; + bool isHKSBarSwitchedToBearish = + cHKSBarO > cHKSBarC && + pHKSBarO <= pHKSBarC; + + // + // TREND ... + + // + bool isTrendUp = + cTrend > pTrend; + bool isTrendDown = + cTrend < pTrend; + + // + bool isTrendBullish = + cTrendState > 0; + bool isTrendBearish = + cTrendState < 0; + + // + bool isTrendSwitchedToBullish = + isTrendUp && + cTrendState > 0 && + pTrendState <= 0; + bool isTrendSwitchedToBearish = + isTrendDown && + cTrendState < 0 && + pTrendState >= 0; + + // + // PEAK ... + + // + bool isPeakSameLast = + cPEAK > 0 && + cPEAK == pPEAK; + bool isPeakOverLast = + pPEAK > 0 && + cPEAK > pPEAK; + bool isPeakUnderLast = + cPEAK > 0 && + cPEAK < pPEAK; + + // + // VALE ... + + // + bool isValeSameLast = + cVALE > 0 && + cVALE == pVALE; + bool isValeOverLast = + pVALE > 0 && + cVALE > pVALE; + bool isValeUnderLast = + cVALE > 0 && + cVALE < pVALE; + + // + // Attached ... + + // + conditions.isATRUp = isATRUp; + conditions.isRSIOB = isRSIOB; + conditions.isRSIOS = isRSIOS; + conditions.isDeltaUp = isDeltaUp; + conditions.isATRDown = isATRDown; + conditions.isTrendUp = isTrendUp; + conditions.rsiOBLevel = _rsiOBLevel; + conditions.rsiOSLevel = _rsiOSLevel; + conditions.isDeltaDown = isDeltaDown; + conditions.isTrendDown = isTrendDown; + conditions.adxThreshold = _adxThreshold; + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isADXBullish = isADXBullish; + conditions.isADXBearish = isADXBearish; + conditions.isRSIBullish = isRSIBullish; + conditions.isRSIBearish = isRSIBearish; + conditions.isSBarBullish = isSBarBullish; + conditions.isSBarBearish = isSBarBearish; + conditions.isDeltaBullish = isDeltaBullish; + conditions.isDeltaBearish = isDeltaBearish; + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isPeakSameLast = isPeakSameLast; + conditions.isPeakOverLast = isPeakOverLast; + conditions.isValeSameLast = isValeSameLast; + conditions.isValeOverLast = isValeOverLast; + conditions.isVolumeBullish = isVolumeBullish; + conditions.isVolumeBearish = isVolumeBearish; + conditions.isADXBiggerLast = isADXBiggerLast; + conditions.isADXLesserLast = isADXLesserLast; + conditions.isHKSBarBullish = isHKSBarBullish; + conditions.isHKSBarBearish = isHKSBarBearish; + conditions.isPeakUnderLast = isPeakUnderLast; + conditions.isValeUnderLast = isValeUnderLast; + conditions.isRSICrossedOverOB = isRSICrossedOverOB; + conditions.isRSICrossedOverOS = isRSICrossedOverOS; + conditions.isADXOverThreshold = isADXOverThreshold; + conditions.isDXPBiggerThanDXN = isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = isDXNBiggerThanDXP; + conditions.isRSICrossedUnderOB = isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = isRSICrossedUnderOS; + conditions.isADXUnderThreshold = isADXUnderThreshold; + conditions.isClosedOverATRUpper = isClosedOverATRUpper; + conditions.isClosedUnderATRLower = isClosedUnderATRLower; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isADXSwitchedToBullish = isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = isADXSwitchedToBearish; + conditions.isRSISwitchedToBullish = isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = isRSISwitchedToBearish; + conditions.isSBarSwitchedToBullish = isSBarSwitchedToBullish; + conditions.isSBarSwitchedToBearish = isSBarSwitchedToBearish; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + conditions.isDeltaSwitchedToBullish = isDeltaSwitchedToBullish; + conditions.isDeltaSwitchedToBearish = isDeltaSwitchedToBearish; + conditions.isVolumeSwitchedToBullish = isVolumeSwitchedToBullish; + conditions.isVolumeSwitchedToBearish = isVolumeSwitchedToBearish; + conditions.isHKSBarSwitchedToBullish = isHKSBarSwitchedToBullish; + conditions.isHKSBarSwitchedToBearish = isHKSBarSwitchedToBearish; + + // + // Cleanup Resources ... + + // + Cleanup(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCatbInputs mInputs; // Inputs ... + + // + // Buffers ... + // Define in Public ... + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_STATE_LINE, + barIndex, + maxRequiredBars, + sarStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_GOLDEN_LINE, + barIndex, + maxRequiredBars, + peakGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_GOLDEN_LINE, + barIndex, + maxRequiredBars, + valeGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_UPPER_LINE, + barIndex, + maxRequiredBars, + atrUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_LOWER_LINE, + barIndex, + maxRequiredBars, + atrLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_LINE, + barIndex, + maxRequiredBars, + trendBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_STATE_LINE, + barIndex, + maxRequiredBars, + trendStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_O_LINE, + barIndex, + maxRequiredBars, + sBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_C_LINE, + barIndex, + maxRequiredBars, + sBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_O_LINE, + barIndex, + maxRequiredBars, + hkSBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_C_LINE, + barIndex, + maxRequiredBars, + hkSBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_RSI_LINE, + barIndex, + maxRequiredBars, + rsiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADX_LINE, + barIndex, + maxRequiredBars, + adxBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXP_LINE, + barIndex, + maxRequiredBars, + adxpBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXN_LINE, + barIndex, + maxRequiredBars, + adxnBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_LINE, + barIndex, + maxRequiredBars, + deltaBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_SIGNAL_LINE, + barIndex, + maxRequiredBars, + deltaSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BULLISH_LINE, + barIndex, + maxRequiredBars, + bullishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BEARISH_LINE, + barIndex, + maxRequiredBars, + bearishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bullishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bearishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_LINE, + barIndex, + maxRequiredBars, + atrBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_O_LINE, + barIndex, + maxRequiredBars, + hkOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_H_LINE, + barIndex, + maxRequiredBars, + hkHighBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_L_LINE, + barIndex, + maxRequiredBars, + hkLowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_C_LINE, + barIndex, + maxRequiredBars, + hkCloseBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxpBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxnBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkCloseBuffer, + maxAllowed // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..6771036 --- /dev/null +++ b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 @@ -0,0 +1,259 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCCInputs +{ + // + // Props ... + + // + // Chart Style ... + ENUM_CHART_MODE mode; // Mode + color upColor; // Up Color + color downColor; // Down Color + color lineColor; // Line mode and Doji candlestick Color + color bearishColor; // Bullish Color + color bullishColor; // Bearish Color + color volumesColor; // Volumes Color + + // + // Presentation ... + bool showCandles; // Show Candles + + // + // Constructor(s) ... + X121XCCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + mode = CHART_CANDLES; + + // + upColor = CLR_NONE; + downColor = CLR_NONE; + lineColor = CLR_NONE; + bearishColor = CLR_NONE; + bullishColor = CLR_NONE; + volumesColor = CLR_NONE; + + // + showCandles = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + mode = CHART_CANDLES; + + // + upColor = clrLime; + downColor = clrRed; + lineColor = clrLime; + bearishColor = clrRed; + bullishColor = clrLime; + volumesColor = clrGreen; + // + showCandles = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + showCandles = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XCX121XCCHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCCHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCCHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + mInputs.mode, // Mode + mInputs.upColor, // Up Color + mInputs.downColor, // Down Color + mInputs.lineColor, // Line mode and Doji candlestick Color + mInputs.bullishColor, // Bearish Color + mInputs.bearishColor, // Bullish Color + mInputs.volumesColor, // Volumes Color + // + // Presentation ... + "", + mInputs.showCandles // Show Candles + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCCInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..6c5284e --- /dev/null +++ b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 @@ -0,0 +1,241 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCTHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCTInputs +{ + // + // Props ... + + // + string font; // Font + int fontSize; // Font Size; + color clr; // Text Color + ENUM_BASE_CORNER corner; // Text Position + + // + // Presentation ... + bool showCandleTime; // Show Candle Time + + // + // Constructor(s) ... + X121XCTInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + font = NULL; + fontSize = 15; + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + font = "Arial"; + fontSize = 15; + clr = clrYellow; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + showCandleTime = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XCX121XCTHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCTHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCTHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xct", + // + // Inputs ... + mInputs.fontSize, // Font Size ... + mInputs.font, // Font ... + mInputs.clr, // Text Color ... + mInputs.corner, // Text Position ... + // + // Presentation ... + "", + mInputs.showCandleTime // Show Candle Time + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 new file mode 100644 index 0000000..720c8d3 --- /dev/null +++ b/BKPS/14040626/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 @@ -0,0 +1,3498 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XOCSHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Buffers ... +enum ENUM_X121_XOSCS_BUFFERS +{ + // + // https://www.mql5.com/en/articles/11467 ... + X121_XOSCS_XAC_LINE = 0, + // https://www.mql5.com/en/articles/10993 ... + X121_XOSCS_XAD_LINE = 1, + // https://www.mql5.com/en/articles/10715 ... + X121_XOSCS_XADX_LINE = 2, + X121_XOSCS_XADX_P_LINE = 3, + X121_XOSCS_XADX_N_LINE = 4, + // https://www.mql5.com/en/articles/10748 ... + X121_XOSCS_XATR_LINE = 5, + // https://www.mql5.com/en/articles/10592 ... + X121_XOSCS_XCCI_LINE = 6, + // https://www.mql5.com/en/articles/10528 ... + X121_XOSCS_XRSI_LINE = 7, + // https://www.mql5.com/en/articles/11037 ... + X121_XOSCS_XMFI_LINE = 8, + // https://www.mql5.com/en/articles/11425 ... + X121_XOSCS_XRVI_LINE = 9, + X121_XOSCS_XRVI_S_LINE = 10, + // https://www.mql5.com/en/articles/10674 ... + X121_XOSCS_XMACD_LINE = 11, + X121_XOSCS_XMACD_S_LINE = 12, + // https://www.mql5.com/en/articles/10547 ... + X121_XOSCS_XMOMENTUM_LINE = 13, + // https://www.mql5.com/en/articles/10692 .. + X121_XOSCS_XSTOCHASTIC_LINE = 14, + X121_XOSCS_XSTOCHASTIC_S_LINE = 15, +}; + +// +// Inputs ... +struct X121XOCSInputs +{ + // + // Props ... + + // + // Accumulation/Distribution ... + ENUM_APPLIED_VOLUME adAppliedTo; // Applied To + + // + // AC ... + int acBullishLevel; // Bullish Level + int acBearishLevel; // Bearish Level + + // + // ADX ... + int adxLength; // Length + int adxThreshold; // Big Movement Threshold + + // + // ATR ... + int atrLength; // Length + + // + // CCI ... + int cciLength; // Length + ENUM_APPLIED_PRICE cciAppliedTo; // Applied To + int cciOBLevel; // Over Bought Level + int cciOSLevel; // Over Sold Level + int cciReversalLevel; // Reversal Level + + // + // RSI ... + int rsiLength; // Length + ENUM_APPLIED_PRICE rsiAppliedTo; // Applied To + int rsiOBLevel; // Over Bought Level + int rsiOSLevel; // Over Sold Level + int rsiReversalLevel; // Reversal Level + + // + // MFI ... + int mfiLength; // Length + ENUM_APPLIED_VOLUME mfiAppliedTo; // Applied To + int mfiOBLevel; // Over Bought Level + int mfiOSLevel; // Over Sold Level + int mfiReversalLevel; // Reversal Level + + // + // RVI ... + int rviLength; // Length + int rviBullishLevel; // Bullish Level + int rviBearishLevel; // Bearish Level + + // + // MACD ... + int macdFastLength; // Fast EMA Length + int macdSlowLength; // Slow EMA Length + int macdSignalLength; // Signal Length + ENUM_APPLIED_PRICE macdAppliedTo; // Applied To + int macdBullishLevel; // Bullish Level + int macdBearishLevel; // Bearish Level + + // + // Momentum ... + int momentumLength; // Length + ENUM_APPLIED_PRICE momentumAppliedTo; // Applied To + int momentumBullishLevel; // Bullish Level + int momentumBearishLevel; // Bearish Level + + // + // Stochastic ... + int stochasticKLength; // K Length (Bars for Calculation) + int stochasticDLength; // D Length (first Smoothing) + int stochasticSmoothingLength; // Smoothing Length + ENUM_MA_METHOD stochasticSmoothingMethod; // Smoothing Method + ENUM_STO_PRICE stochasticAppliedTo; // Applied To + int stochasticOBLevel; // Over Bought Level + int stochasticOSLevel; // Over Sold Level + int stochasticReversalLevel; // Reversal Level + + // + // Presentation ... + int startCalculationForLastBars; // Calculate Last n Bars + + // + // Constructor(s) ... + X121XOCSInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Accumulation/Distribution ... + adAppliedTo = VOLUME_TICK; // Applied To + + // + // AC ... + acBullishLevel = 0; + acBearishLevel = 0; + + // + // ADX ... + adxLength = 0; // Length + adxThreshold = 0; // Big Movement Threshold + + // + // ATR ... + atrLength = 0; // Length + + // + // CCI ... + cciLength = 0; // Length + cciAppliedTo = PRICE_TYPICAL; // Applied To + cciOBLevel = 100; // Over Bought Level + cciOSLevel = -100; // Over Sold Level + cciReversalLevel = 0; // Reversal Level + + // + // RSI ... + rsiLength = 0; // Length + rsiAppliedTo = PRICE_CLOSE; // Applied To + rsiOBLevel = 0; // Over Bought Level + rsiOSLevel = 0; // Over Sold Level + rsiReversalLevel = 0; // Reversal Level + + // + // MFI ... + mfiLength = 0; // Length + mfiAppliedTo = VOLUME_TICK; // Applied To + mfiOBLevel = 0; // Over Bought Level + mfiOSLevel = 0; // Over Sold Level + mfiReversalLevel = 0; // Reversal Level + + // + // RVI ... + rviLength = 0; // Length + rviBullishLevel = 0; // Bullish Level + rviBearishLevel = 0; // Bearish Level + + // + // MACD ... + macdFastLength = 0; // Fast EMA Length + macdSlowLength = 0; // Slow EMA Length + macdSignalLength = 0; // Signal Length + macdAppliedTo = PRICE_CLOSE; // Applied To + macdBullishLevel = 0; // Bullish Level + macdBearishLevel = 0; // Bearish Level + + // + // Momentum ... + momentumLength = 0; // Length + momentumAppliedTo = PRICE_CLOSE; // Applied To + momentumBullishLevel = 0; // Bullish Level + momentumBearishLevel = 0; // Bearish Level + + // + // Stochastic ... + stochasticKLength = 0; // K Length (Bars for Calculation) + stochasticDLength = 0; // D Length (first Smoothing) + stochasticSmoothingLength = 0; // Smoothing Length + stochasticSmoothingMethod = MODE_SMA; // Smoothing Method + stochasticAppliedTo = STO_LOWHIGH; // Applied To + stochasticOBLevel = 0; // Over Bought Level + stochasticOSLevel = 0; // Over Sold Level + stochasticReversalLevel = 0; // Reversal Level + + // + // Presentation ... + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Accumulation/Distribution ... + adAppliedTo = VOLUME_TICK; // Applied To + + // + // AC ... + acBullishLevel = 0; + acBearishLevel = 0; + + // + // ADX ... + adxLength = 14; // Length + adxThreshold = 25; // Big Movement Threshold + + // + // ATR ... + atrLength = 14; // Length + + // + // CCI ... + cciLength = 14; // Length + cciAppliedTo = PRICE_TYPICAL; // Applied To + cciOBLevel = 100; // Over Bought Level + cciOSLevel = -100; // Over Sold Level + cciReversalLevel = 0; // Reversal Level + + // + // RSI ... + rsiLength = 14; // Length + rsiAppliedTo = PRICE_CLOSE; // Applied To + rsiOBLevel = 70; // Over Bought Level + rsiOSLevel = 30; // Over Sold Level + rsiReversalLevel = 50; // Reversal Level + + // + // MFI ... + mfiLength = 14; // Length + mfiAppliedTo = VOLUME_TICK; // Applied To + mfiOBLevel = 80; // Over Bought Level + mfiOSLevel = 20; // Over Sold Level + mfiReversalLevel = 50; // Reversal Level + + // + // RVI ... + rviLength = 14; // Length + rviBullishLevel = 0; // Bullish Level + rviBearishLevel = 0; // Bearish Level + + // + // MACD ... + macdFastLength = 12; // Fast EMA Length + macdSlowLength = 26; // Slow EMA Length + macdSignalLength = 9; // Signal Length + macdAppliedTo = PRICE_CLOSE; // Applied To + macdBullishLevel = 0; // Bullish Level + macdBearishLevel = 0; // Bearish Level + + // + // Momentum ... + momentumLength = 14; // Length + momentumAppliedTo = PRICE_CLOSE; // Applied To + momentumBullishLevel = 100; // Bullish Level + momentumBearishLevel = 100; // Bearish Level + + // + // Stochastic ... + stochasticKLength = 5; // K Length (Bars for Calculation) + stochasticDLength = 3; // D Length (first Smoothing) + stochasticSmoothingLength = 3; // Smoothing Length + stochasticSmoothingMethod = MODE_SMA; // Smoothing Method + stochasticAppliedTo = STO_LOWHIGH; // Applied To + stochasticOBLevel = 80; // Over Bought Level + stochasticOSLevel = 20; // Over Sold Level + stochasticReversalLevel = 50; // Reversal Level + + // + // Presentation ... + startCalculationForLastBars = 1000; // Calculate Last n Bars + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + adxLength > 0 && + adxThreshold > 0 && + // + atrLength > 0 && + // + cciLength > 0 && + cciOBLevel > 0 && + cciOSLevel != 0 && + cciOBLevel > cciReversalLevel && + cciOSLevel < cciReversalLevel && + // + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + rsiReversalLevel > 0 && + rsiOBLevel > rsiReversalLevel && + rsiOSLevel < rsiReversalLevel && + // + mfiLength > 0 && + mfiOBLevel > 0 && + mfiOSLevel > 0 && + mfiReversalLevel > 0 && + mfiOBLevel > mfiReversalLevel && + mfiOSLevel < mfiReversalLevel && + // + rviLength > 0 && + // + macdFastLength > 0 && + macdSlowLength > 0 && + macdSignalLength > 0 && + macdFastLength < macdSlowLength && + // + stochasticKLength > 0 && + stochasticDLength > 0 && + stochasticSmoothingLength > 0 && + stochasticOBLevel > 0 && + stochasticOSLevel > 0 && + stochasticReversalLevel > 0 && + stochasticOBLevel > stochasticReversalLevel && + stochasticOSLevel < stochasticReversalLevel && + // + momentumLength > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(adxLength, atrLength); + result = MathMax(result, cciLength); + result = MathMax(result, rsiLength); + result = MathMax(result, mfiLength); + result = MathMax(result, rviLength); + result = MathMax(result, momentumLength); + result = MathMax(result, macdFastLength); + result = MathMax(result, macdSlowLength); + result = MathMax(result, macdSignalLength); + result = MathMax(result, stochasticKLength); + result = MathMax(result, stochasticDLength); + result = MathMax(result, stochasticSmoothingLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XOCSConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double acBuffer[]; + double adBuffer[]; + double atrBuffer[]; + double cciBuffer[]; + double rsiBuffer[]; + double mfiBuffer[]; + double rviBuffer[]; + double adxBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double macdBuffer[]; + double momentumBuffer[]; + double rviSignalBuffer[]; + double macdSignalBuffer[]; + double stochasticBuffer[]; + double stochasticSignalBuffer[]; + + // + // Values ... + + // + double adxThreshold; // Big Movement Threshold + double cciOBLevel; // Over Bought Level + double cciOSLevel; // Over Sold Level + double cciReversalLevel; // Reversal Level + double rsiOBLevel; // Over Bought Level + double rsiOSLevel; // Over Sold Level + double rsiReversalLevel; // Reversal Level + double mfiOBLevel; // Over Bought Level + double mfiOSLevel; // Over Sold Level + double mfiReversalLevel; // Reversal Level + double rviBullishLevel; // Bullish Level + double rviBearishLevel; // Bearish Level + double macdBullishLevel; // Bullish Level + double macdBearishLevel; // Bearish Level + double momentumBullishLevel; // Bullish Level + double momentumBearishLevel; // Bearish Level + double stochasticOBLevel; // Over Bought Level + double stochasticOSLevel; // Over Sold Level + double stochasticReversalLevel; // Reversal Level + + // + // Conditions ... + + // + // AC ... + + // + bool isACBullish; + bool isACBearish; + + // + bool isACSwitchedToBullish; + bool isACSwitchedToBearish; + + // + bool isACOverMax; + bool isACUnderMin; + + // + // AD ... + + // + bool isADBiggerLast; + bool isADLesserLast; + + // + bool isADOverMax; + bool isADUnderMin; + + // + // ADX ... + + // + bool isADXBiggerLast; + bool isADXLesserLast; + + // + bool isADXOverThreshold; + bool isADXUnderThreshold; + + // + bool isDXPBiggerThanDXN; + bool isDXNBiggerThanDXP; + + // + bool isADXBullish; + bool isADXBearish; + + // + bool isADXSwitchedToBullish; + bool isADXSwitchedToBearish; + + // + // ATR ... + + bool isATROverLast; + bool isATRUnderLast; + + // + // CCI ... + + // + bool isCCIBullish; + bool isCCIBearish; + + // + bool isCCISwitchedToBullish; + bool isCCISwitchedToBearish; + + // + bool isCCIOB; + bool isCCIOS; + + // + bool isCCICrossedOverOB; + bool isCCICrossedOverOS; + + // + bool isCCICrossedUnderOB; + bool isCCICrossedUnderOS; + + // + // RSI ... + + // + bool isRSIBullish; + bool isRSIBearish; + + // + bool isRSISwitchedToBullish; + bool isRSISwitchedToBearish; + + // + bool isRSIOB; + bool isRSIOS; + + // + bool isRSICrossedOverOB; + bool isRSICrossedOverOS; + + // + bool isRSICrossedUnderOB; + bool isRSICrossedUnderOS; + + // + // MFI ... + + // + bool isMFIBullish; + bool isMFIBearish; + + // + bool isMFISwitchedToBullish; + bool isMFISwitchedToBearish; + + // + bool isMFIOB; + bool isMFIOS; + + // + bool isMFICrossedOverOB; + bool isMFICrossedOverOS; + + // + bool isMFICrossedUnderOB; + bool isMFICrossedUnderOS; + + // + // RVI ... + + // + bool isRVIBullish; + bool isRVIBearish; + + // + bool isRVISwitchedToBullish; + bool isRVISwitchedToBearish; + + // + bool isRVIOverSignal; + bool isRVIUnderSignal; + + // + bool isRVICrossedOverSignal; + bool isRVICrossedUnderSignal; + + // + // MACD ... + + // + bool isMACDBullish; + bool isMACDBearish; + + // + bool isMACDSwitchedToBullish; + bool isMACDSwitchedToBearish; + + // + bool isMACDOverSignal; + bool isMACDUnderSignal; + + // + bool isMACDCrossedOverSignal; + bool isMACDCrossedUnderSignal; + + // + // MOMENTUM ... + + // + bool isMomentumBullish; + bool isMomentumBearish; + + // + bool isMomentumSwitchedToBullish; + bool isMomentumSwitchedToBearish; + + // + // STOCHASTIC ... + + // + bool isStochasticBullish; + bool isStochasticBearish; + + // + bool isStochasticSwitchedToBullish; + bool isStochasticSwitchedToBearish; + + // + bool isStochasticOverSignal; + bool isStochasticUnderSignal; + + // + bool isStochasticCrossedOverSignal; + bool isStochasticCrossedUnderSignal; + + // + bool isStochasticOB; + bool isStochasticOS; + + // + bool isStochasticCrossedOverOB; + bool isStochasticCrossedOverOS; + + // + bool isStochasticCrossedUnderOB; + bool isStochasticCrossedUnderOS; + + // + // Constructor ... + X121XOCSConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(acBuffer); + Clean(adBuffer); + Clean(atrBuffer); + Clean(cciBuffer); + Clean(rsiBuffer); + Clean(mfiBuffer); + Clean(rviBuffer); + Clean(adxBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(macdBuffer); + Clean(momentumBuffer); + Clean(rviSignalBuffer); + Clean(macdSignalBuffer); + Clean(stochasticBuffer); + Clean(stochasticSignalBuffer); + + // + ArraySetAsSeries(acBuffer, true); + ArraySetAsSeries(adBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(cciBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(mfiBuffer, true); + ArraySetAsSeries(rviBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(macdBuffer, true); + ArraySetAsSeries(momentumBuffer, true); + ArraySetAsSeries(rviSignalBuffer, true); + ArraySetAsSeries(macdSignalBuffer, true); + ArraySetAsSeries(stochasticBuffer, true); + ArraySetAsSeries(stochasticSignalBuffer, true); + + // + // Values ... + + // + adxThreshold = 0.0; + cciOBLevel = 0.0; + cciOSLevel = 0.0; + cciReversalLevel = 0.0; + rsiOBLevel = 0.0; + rsiOSLevel = 0.0; + rsiReversalLevel = 0.0; + mfiOBLevel = 0.0; + mfiOSLevel = 0.0; + mfiReversalLevel = 0.0; + rviBullishLevel = 0.0; + rviBearishLevel = 0.0; + macdBullishLevel = 0.0; + macdBearishLevel = 0.0; + momentumBullishLevel = 0.0; + momentumBearishLevel = 0.0; + stochasticOBLevel = 0.0; + stochasticOSLevel = 0.0; + stochasticReversalLevel = 0.0; + + // + // Conditions ... + + // + // AC ... + + // + isACBullish = false; + isACBearish = false; + isACSwitchedToBullish = false; + isACSwitchedToBearish = false; + isACOverMax = false; + isACUnderMin = false; + + // + // AD ... + + // + isADBiggerLast = false; + isADLesserLast = false; + isADOverMax = false; + isADUnderMin = false; + + // + // ADX ... + + // + isADXBiggerLast = false; + isADXLesserLast = false; + isADXOverThreshold = false; + isADXUnderThreshold = false; + isDXPBiggerThanDXN = false; + isDXNBiggerThanDXP = false; + isADXBullish = false; + isADXBearish = false; + isADXSwitchedToBullish = false; + isADXSwitchedToBearish = false; + + // + // ATR ... + + // + isATROverLast = false; + isATRUnderLast = false; + + // + // CCI ... + + // + isCCIBullish = false; + isCCIBearish = false; + isCCISwitchedToBullish = false; + isCCISwitchedToBearish = false; + isCCIOB = false; + isCCIOS = false; + isCCICrossedOverOB = false; + isCCICrossedOverOS = false; + isCCICrossedUnderOB = false; + isCCICrossedUnderOS = false; + + // + // RSI ... + + // + isRSIBullish = false; + isRSIBearish = false; + isRSISwitchedToBullish = false; + isRSISwitchedToBearish = false; + isRSIOB = false; + isRSIOS = false; + isRSICrossedOverOB = false; + isRSICrossedOverOS = false; + isRSICrossedUnderOB = false; + isRSICrossedUnderOS = false; + + // + // MFI ... + + // + isMFIBullish = false; + isMFIBearish = false; + isMFISwitchedToBullish = false; + isMFISwitchedToBearish = false; + isMFIOB = false; + isMFIOS = false; + isMFICrossedOverOB = false; + isMFICrossedOverOS = false; + isMFICrossedUnderOB = false; + isMFICrossedUnderOS = false; + + // + // RVI ... + + // + isRVIBullish = false; + isRVIBearish = false; + isRVISwitchedToBullish = false; + isRVISwitchedToBearish = false; + isRVIOverSignal = false; + isRVIUnderSignal = false; + isRVICrossedOverSignal = false; + isRVICrossedUnderSignal = false; + + // + // MACD ... + + // + isMACDBullish = false; + isMACDBearish = false; + isMACDSwitchedToBullish = false; + isMACDSwitchedToBearish = false; + isMACDOverSignal = false; + isMACDUnderSignal = false; + isMACDCrossedOverSignal = false; + isMACDCrossedUnderSignal = false; + + // + // MOMENTUM ... + + // + isMomentumBullish = false; + isMomentumBearish = false; + isMomentumSwitchedToBullish = false; + isMomentumSwitchedToBearish = false; + + // + // STOCHASTIC ... + + // + isStochasticBullish = false; + isStochasticBearish = false; + isStochasticSwitchedToBullish = false; + isStochasticSwitchedToBearish = false; + isStochasticOverSignal = false; + isStochasticUnderSignal = false; + isStochasticCrossedOverSignal = false; + isStochasticCrossedUnderSignal = false; + isStochasticOB = false; + isStochasticOS = false; + isStochasticCrossedOverOB = false; + isStochasticCrossedOverOS = false; + isStochasticCrossedUnderOB = false; + isStochasticCrossedUnderOS = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + + // + // AC ... + + // + if (isACBullish) + { + bullishScore += minScore; + } + if (isACOverMax) + { + bullishScore += minScore; + } + if (isACSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isACBearish) + { + bearishScore += minScore; + } + if (isACUnderMin) + { + bearishScore += minScore; + } + if (isACSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // AD ... + + // + if (isADOverMax) + { + bullishScore += minScore; + } + if (isADBiggerLast) + { + bullishScore += minScore; + } + + // + if (isADUnderMin) + { + bearishScore += minScore; + } + if (isADLesserLast) + { + bearishScore += minScore; + } + + // + // ADX ... + + // + if (isADXBullish) + { + bullishScore += minScore; + } + if (isADXBiggerLast) + { + bullishScore += minScore; + } + if (isADXOverThreshold) + { + bullishScore += minScore; + } + if (isDXPBiggerThanDXN) + { + bullishScore += minScore; + } + if (isADXSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isADXBearish) + { + bearishScore += minScore; + } + if (isADXLesserLast) + { + bearishScore += minScore; + } + if (isDXNBiggerThanDXP) + { + bearishScore += minScore; + } + if (isADXUnderThreshold) + { + bearishScore += minScore; + } + if (isADXSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // ATR ... + + // + if (isATROverLast) + { + bullishScore += minScore; + } + + // + if (isATRUnderLast) + { + bearishScore += minScore; + } + + // + // CCI ... + + // + if (isCCIOS) + { + bullishScore += minScore; + } + if (isCCIBullish) + { + bullishScore += minScore; + } + if (isCCICrossedOverOS) + { + bullishScore += minScore; + } + if (isCCICrossedOverOB) + { + bullishScore += minScore; + } + if (isCCISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isCCIOB) + { + bearishScore += minScore; + } + if (isCCIBearish) + { + bearishScore += minScore; + } + if (isCCICrossedUnderOS) + { + bearishScore += minScore; + } + if (isCCICrossedUnderOB) + { + bearishScore += minScore; + } + if (isCCISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // RSI ... + + // + if (isRSIOS) + { + bullishScore += minScore; + } + if (isRSIBullish) + { + bullishScore += minScore; + } + if (isRSICrossedOverOB) + { + bullishScore += minScore; + } + if (isRSICrossedOverOS) + { + bullishScore += minScore; + } + if (isRSISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isRSIOB) + { + bearishScore += minScore; + } + if (isRSIBearish) + { + bearishScore += minScore; + } + if (isRSICrossedUnderOB) + { + bearishScore += minScore; + } + if (isRSICrossedUnderOS) + { + bearishScore += minScore; + } + if (isRSISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // MFI ... + + // + if (isMFIOS) + { + bullishScore += minScore; + } + if (isMFIBullish) + { + bullishScore += minScore; + } + if (isMFICrossedOverOB) + { + bullishScore += minScore; + } + if (isMFICrossedOverOS) + { + bullishScore += minScore; + } + if (isMFISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isMFIOB) + { + bearishScore += minScore; + } + if (isMFIBearish) + { + bearishScore += minScore; + } + if (isMFICrossedUnderOB) + { + bearishScore += minScore; + } + if (isMFICrossedUnderOS) + { + bearishScore += minScore; + } + if (isMFISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // RVI ... + + // + if (isRVIBullish) + { + bullishScore += minScore; + } + if (isRVIOverSignal) + { + bullishScore += minScore; + } + if (isRVISwitchedToBullish) + { + bullishScore += minScore; + } + if (isRVICrossedOverSignal) + { + bullishScore += minScore; + } + + // + if (isRVIBearish) + { + bearishScore += minScore; + } + if (isRVIUnderSignal) + { + bearishScore += minScore; + } + if (isRVISwitchedToBearish) + { + bearishScore += minScore; + } + if (isRVICrossedUnderSignal) + { + bearishScore += minScore; + } + + // + // MACD ... + + // + if (isMACDBullish) + { + bullishScore += minScore; + } + if (isMACDOverSignal) + { + bullishScore += minScore; + } + if (isMACDSwitchedToBullish) + { + bullishScore += minScore; + } + if (isMACDCrossedOverSignal) + { + bullishScore += minScore; + } + + // + if (isMACDBearish) + { + bearishScore += minScore; + } + if (isMACDUnderSignal) + { + bearishScore += minScore; + } + if (isMACDSwitchedToBearish) + { + bearishScore += minScore; + } + if (isMACDCrossedUnderSignal) + { + bearishScore += minScore; + } + + // + // MOMENTUM ... + + // + if (isMomentumBullish) + { + bullishScore += minScore; + } + if (isMomentumSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isMomentumBearish) + { + bearishScore += minScore; + } + if (isMomentumSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // STOCHASTIC ... + + // + if (isStochasticOS) + { + bullishScore += minScore; + } + if (isStochasticOverSignal) + { + bullishScore += minScore; + } + if (isStochasticBullish) + { + bullishScore += minScore; + } + if (isStochasticCrossedOverSignal) + { + bullishScore += minScore; + } + if (isStochasticCrossedOverOB) + { + bullishScore += minScore; + } + if (isStochasticCrossedOverOS) + { + bullishScore += minScore; + } + if (isStochasticSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isStochasticOB) + { + bearishScore += minScore; + } + if (isStochasticUnderSignal) + { + bearishScore += minScore; + } + if (isStochasticBearish) + { + bearishScore += minScore; + } + if (isStochasticCrossedUnderSignal) + { + bearishScore += minScore; + } + if (isStochasticCrossedUnderOB) + { + bearishScore += minScore; + } + if (isStochasticCrossedUnderOS) + { + bearishScore += minScore; + } + if (isStochasticSwitchedToBearish) + { + bearishScore += minScore; + } + + // + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XOSCS: " + separator + + "-----------------------" + separator + + ToString("isACBullish", isACBullish, ignoreFalseConditions, separator) + + ToString("isACBearish", isACBearish, ignoreFalseConditions, separator) + + ToString("isACSwitchedToBullish", isACSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isACSwitchedToBearish", isACSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isACOverMax", isACOverMax, ignoreFalseConditions, separator) + + ToString("isACUnderMin", isACUnderMin, ignoreFalseConditions, separator) + + ToString("isADBiggerLast", isADBiggerLast, ignoreFalseConditions, separator) + + ToString("isADLesserLast", isADLesserLast, ignoreFalseConditions, separator) + + ToString("isADOverMax", isADOverMax, ignoreFalseConditions, separator) + + ToString("isADUnderMin", isADUnderMin, ignoreFalseConditions, separator) + + ToString("isADXBiggerLast", isADXBiggerLast, ignoreFalseConditions, separator) + + ToString("isADXLesserLast", isADXLesserLast, ignoreFalseConditions, separator) + + ToString("isADXOverThreshold", isADXOverThreshold, ignoreFalseConditions, separator) + + ToString("isADXUnderThreshold", isADXUnderThreshold, ignoreFalseConditions, separator) + + ToString("isDXPBiggerThanDXN", isDXPBiggerThanDXN, ignoreFalseConditions, separator) + + ToString("isDXNBiggerThanDXP", isDXNBiggerThanDXP, ignoreFalseConditions, separator) + + ToString("isADXBullish", isADXBullish, ignoreFalseConditions, separator) + + ToString("isADXBearish", isADXBearish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBullish", isADXSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBearish", isADXSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isATROverLast", isATROverLast, ignoreFalseConditions, separator) + + ToString("isATRUnderLast", isATRUnderLast, ignoreFalseConditions, separator) + + ToString("isCCIBullish", isCCIBullish, ignoreFalseConditions, separator) + + ToString("isCCIBearish", isCCIBearish, ignoreFalseConditions, separator) + + ToString("isCCISwitchedToBullish", isCCISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isCCISwitchedToBearish", isCCISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isCCIOB", isCCIOB, ignoreFalseConditions, separator) + + ToString("isCCIOS", isCCIOS, ignoreFalseConditions, separator) + + ToString("isCCICrossedOverOB", isCCICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isCCICrossedOverOS", isCCICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isCCICrossedUnderOB", isCCICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isCCICrossedUnderOS", isCCICrossedUnderOS, ignoreFalseConditions, separator) + + ToString("isRSIBullish", isRSIBullish, ignoreFalseConditions, separator) + + ToString("isRSIBearish", isRSIBearish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBullish", isRSISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBearish", isRSISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRSIOB", isRSIOB, ignoreFalseConditions, separator) + + ToString("isRSIOS", isRSIOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOB", isRSICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOS", isRSICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOB", isRSICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOS", isRSICrossedUnderOS, ignoreFalseConditions, separator) + + ToString("isMFIBullish", isMFIBullish, ignoreFalseConditions, separator) + + ToString("isMFIBearish", isMFIBearish, ignoreFalseConditions, separator) + + ToString("isMFISwitchedToBullish", isMFISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMFISwitchedToBearish", isMFISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMFIOB", isMFIOB, ignoreFalseConditions, separator) + + ToString("isMFIOS", isMFIOS, ignoreFalseConditions, separator) + + ToString("isMFICrossedOverOB", isMFICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isMFICrossedOverOS", isMFICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isMFICrossedUnderOB", isMFICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isMFICrossedUnderOS", isMFICrossedUnderOS, ignoreFalseConditions, separator) + + ToString("isRVIBullish", isRVIBullish, ignoreFalseConditions, separator) + + ToString("isRVIBearish", isRVIBearish, ignoreFalseConditions, separator) + + ToString("isRVISwitchedToBullish", isRVISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRVISwitchedToBearish", isRVISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRVIOverSignal", isRVIOverSignal, ignoreFalseConditions, separator) + + ToString("isRVIUnderSignal", isRVIUnderSignal, ignoreFalseConditions, separator) + + ToString("isRVICrossedOverSignal", isRVICrossedOverSignal, ignoreFalseConditions, separator) + + ToString("isRVICrossedUnderSignal", isRVICrossedUnderSignal, ignoreFalseConditions, separator) + + ToString("isMACDBullish", isMACDBullish, ignoreFalseConditions, separator) + + ToString("isMACDBearish", isMACDBearish, ignoreFalseConditions, separator) + + ToString("isMACDSwitchedToBullish", isMACDSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMACDSwitchedToBearish", isMACDSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMACDOverSignal", isMACDOverSignal, ignoreFalseConditions, separator) + + ToString("isMACDUnderSignal", isMACDUnderSignal, ignoreFalseConditions, separator) + + ToString("isMACDCrossedOverSignal", isMACDCrossedOverSignal, ignoreFalseConditions, separator) + + ToString("isMACDCrossedUnderSignal", isMACDCrossedUnderSignal, ignoreFalseConditions, separator) + + ToString("isMomentumBullish", isMomentumBullish, ignoreFalseConditions, separator) + + ToString("isMomentumBearish", isMomentumBearish, ignoreFalseConditions, separator) + + ToString("isMomentumSwitchedToBullish", isMomentumSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMomentumSwitchedToBearish", isMomentumSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isStochasticBullish", isStochasticBullish, ignoreFalseConditions, separator) + + ToString("isStochasticBearish", isStochasticBearish, ignoreFalseConditions, separator) + + ToString("isStochasticSwitchedToBullish", isStochasticSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isStochasticSwitchedToBearish", isStochasticSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isStochasticOverSignal", isStochasticOverSignal, ignoreFalseConditions, separator) + + ToString("isStochasticUnderSignal", isStochasticUnderSignal, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedOverSignal", isStochasticCrossedOverSignal, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedUnderSignal", isStochasticCrossedUnderSignal, ignoreFalseConditions, separator) + + ToString("isStochasticOB", isStochasticOB, ignoreFalseConditions, separator) + + ToString("isStochasticOS", isStochasticOS, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedOverOB", isStochasticCrossedOverOB, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedOverOS", isStochasticCrossedOverOS, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedUnderOB", isStochasticCrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedUnderOS", isStochasticCrossedUnderOS, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } +}; + +// +// Helper Class Implementation ... +class XCX121XOCSHelper : XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XOCSHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XOCSHelper() + { + // + mInputs.Clean(); + + // + Clean(acBuffer); + Clean(adBuffer); + Clean(atrBuffer); + Clean(cciBuffer); + Clean(rsiBuffer); + Clean(mfiBuffer); + Clean(rviBuffer); + Clean(adxBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(macdBuffer); + Clean(momentumBuffer); + Clean(rviSignalBuffer); + Clean(macdSignalBuffer); + Clean(stochasticBuffer); + Clean(stochasticSignalBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XOCSInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(acBuffer, true); + ArraySetAsSeries(adBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(cciBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(mfiBuffer, true); + ArraySetAsSeries(rviBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(macdBuffer, true); + ArraySetAsSeries(momentumBuffer, true); + ArraySetAsSeries(rviSignalBuffer, true); + ArraySetAsSeries(macdSignalBuffer, true); + ArraySetAsSeries(stochasticBuffer, true); + ArraySetAsSeries(stochasticSignalBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xoscs", + // + // Inputs ... + // + // AD ... + "", + mInputs.adAppliedTo, + // + // ADX ... + "", + mInputs.adxLength, + // + // ATR ... + "", + mInputs.atrLength, + // + // CCI ... + "", + mInputs.cciLength, + mInputs.cciAppliedTo, + // + // RSI ... + "", + mInputs.rsiLength, + mInputs.rsiAppliedTo, + // + // MFI ... + "", + mInputs.mfiLength, + mInputs.mfiAppliedTo, + // + // RVI ... + "", + mInputs.rviLength, + // + // MACD ... + "", + mInputs.macdFastLength, + mInputs.macdSlowLength, + mInputs.macdSignalLength, + mInputs.macdAppliedTo, + // + // MOMENTUM ... + "", + mInputs.momentumLength, + mInputs.momentumAppliedTo, + // + // STOCHASTIC ... + "", + mInputs.stochasticKLength, + mInputs.stochasticDLength, + mInputs.stochasticSmoothingLength, + mInputs.stochasticSmoothingMethod, + mInputs.stochasticAppliedTo, + // + // Presentation ... + "", + // + mInputs.startCalculationForLastBars + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XOCSInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XOCSInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // AC ... + + // + double GetAC( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(acBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return acBuffer[barIndex]; + } + + // + int CopyAC( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + acBuffer, + buffer, + forceClean + // + ); + } + + // + // AD ... + + // + double GetAD( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adBuffer[barIndex]; + } + + // + int CopyAD( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXP ... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxpBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxpBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXN ... + + // + double GetADXN( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxnBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxnBuffer[barIndex]; + } + + // + int CopyADXN( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxnBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // CCI ... + + // + double GetCCI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(cciBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return cciBuffer[barIndex]; + } + + // + int CopyCCI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + cciBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + int CopyRSI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // MFI ... + + // + double GetMFI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mfiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mfiBuffer[barIndex]; + } + + // + int CopyMFI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mfiBuffer, + buffer, + forceClean + // + ); + } + + // + // Momentum ... + + // + double GetMomentum( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(momentumBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return momentumBuffer[barIndex]; + } + + // + int CopyMomentum( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + momentumBuffer, + buffer, + forceClean + // + ); + } + + // + // RVI ... + + // + double GetRVI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rviBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rviBuffer[barIndex]; + } + + // + int CopyRVI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rviBuffer, + buffer, + forceClean + // + ); + } + + // + // RVI Signal ... + + // + double GetRVISignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rviSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rviSignalBuffer[barIndex]; + } + + // + int CopyRVISignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rviSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // MACD ... + + // + double GetMACD( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(macdBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return macdBuffer[barIndex]; + } + + // + int CopyMACD( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + macdBuffer, + buffer, + forceClean + // + ); + } + + // + // MACD Signal ... + + // + double GetMACDSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(macdSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return macdSignalBuffer[barIndex]; + } + + // + int CopyMACDSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + macdSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Stochastic ... + + // + double GetStochastic( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(stochasticBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return stochasticBuffer[barIndex]; + } + + // + int CopyStochastic( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + stochasticBuffer, + buffer, + forceClean + // + ); + } + + // + // Stochastic Signal ... + + // + double GetStochasticSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(stochasticSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return stochasticSignalBuffer[barIndex]; + } + + // + int CopyStochasticSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + stochasticSignalBuffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XOCSConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + CopyAC( + zIndex, + loopback, + conditions.acBuffer // + ); + + // + CopyAD( + zIndex, + loopback, + conditions.adBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxpBuffer // + ); + + // + CopyADXN( + zIndex, + loopback, + conditions.adxnBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyCCI( + zIndex, + loopback, + conditions.cciBuffer // + ); + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + CopyMFI( + zIndex, + loopback, + conditions.mfiBuffer // + ); + + // + CopyMomentum( + zIndex, + loopback, + conditions.momentumBuffer // + ); + + // + CopyRVI( + zIndex, + loopback, + conditions.rviBuffer // + ); + + // + CopyRVISignal( + zIndex, + loopback, + conditions.rviSignalBuffer // + ); + + // + CopyMACD( + zIndex, + loopback, + conditions.macdBuffer // + ); + + // + CopyMACDSignal( + zIndex, + loopback, + conditions.macdSignalBuffer // + ); + + // + CopyStochastic( + zIndex, + loopback, + conditions.stochasticBuffer // + ); + + // + CopyStochasticSignal( + zIndex, + loopback, + conditions.stochasticSignalBuffer // + ); + + // + // Values ... + + // + conditions.adxThreshold = mInputs.adxThreshold; + conditions.cciOBLevel = mInputs.cciOBLevel; + conditions.cciOSLevel = mInputs.cciOSLevel; + conditions.cciReversalLevel = mInputs.cciReversalLevel; + conditions.rsiOBLevel = mInputs.rsiOBLevel; + conditions.rsiOSLevel = mInputs.rsiOSLevel; + conditions.rsiReversalLevel = mInputs.rsiReversalLevel; + conditions.mfiOBLevel = mInputs.mfiOBLevel; + conditions.mfiOSLevel = mInputs.mfiOSLevel; + conditions.mfiReversalLevel = mInputs.mfiReversalLevel; + conditions.rviBullishLevel = mInputs.rviBullishLevel; + conditions.rviBearishLevel = mInputs.rviBearishLevel; + conditions.macdBullishLevel = mInputs.macdBullishLevel; + conditions.macdBearishLevel = mInputs.macdBearishLevel; + conditions.momentumBullishLevel = mInputs.momentumBullishLevel; + conditions.momentumBearishLevel = mInputs.momentumBearishLevel; + conditions.stochasticOBLevel = mInputs.stochasticOBLevel; + conditions.stochasticOSLevel = mInputs.stochasticOSLevel; + conditions.stochasticReversalLevel = mInputs.stochasticReversalLevel; + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + int ppIDX = pIDX + 1; + + // + // AC ... + + // + bool isACBullish = conditions.acBuffer[cIDX] > mInputs.acBullishLevel; + bool isACBullishPrev = conditions.acBuffer[pIDX] > mInputs.acBullishLevel; + bool isACSwitchedToBullish = isACBullish && + !isACBullishPrev; + + // + bool isACBearish = conditions.acBuffer[cIDX] < mInputs.acBearishLevel; + bool isACBearishPrev = conditions.acBuffer[pIDX] < mInputs.acBearishLevel; + bool isACSwitchedToBearish = isACBearish && + !isACBearishPrev; + + // + bool isACOverMax = conditions.acBuffer[cIDX] >= GetMax(conditions.acBuffer); + bool isACUnderMin = conditions.acBuffer[cIDX] <= GetMin(conditions.acBuffer); + + // + // AD ... + + // + bool isADBiggerLast = conditions.adBuffer[cIDX] > conditions.adBuffer[pIDX]; + bool isADLesserLast = conditions.adBuffer[cIDX] < conditions.adBuffer[pIDX]; + + // + bool isADOverMax = conditions.adBuffer[cIDX] >= GetMax(conditions.adBuffer); + bool isADUnderMin = conditions.adBuffer[cIDX] <= GetMin(conditions.adBuffer); + + // + // ADX ... + + // + bool isADXBiggerLast = conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX]; + bool isADXBiggerLastPrev = conditions.adxBuffer[pIDX] > conditions.adxBuffer[ppIDX]; + + // + bool isADXLesserLast = conditions.adxBuffer[cIDX] < conditions.adxBuffer[pIDX]; + bool isADXLesserLastPrev = conditions.adxBuffer[pIDX] < conditions.adxBuffer[ppIDX]; + + // + bool isADXOverThreshold = conditions.adxBuffer[cIDX] > mInputs.adxThreshold; + bool isADXOverThresholdPrev = conditions.adxBuffer[pIDX] > mInputs.adxThreshold; + + // + bool isADXUnderThreshold = conditions.adxBuffer[cIDX] < mInputs.adxThreshold; + bool isADXUnderThresholdPrev = conditions.adxBuffer[pIDX] < mInputs.adxThreshold; + + // + bool isDXPBiggerThanDXN = conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX]; + bool isDXPBiggerThanDXNPrev = conditions.adxpBuffer[pIDX] > conditions.adxnBuffer[pIDX]; + + // + bool isDXNBiggerThanDXP = conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX]; + bool isDXNBiggerThanDXPPrev = conditions.adxnBuffer[pIDX] > conditions.adxpBuffer[pIDX]; + + // + bool isADXBullish = isADXBiggerLast && + isDXPBiggerThanDXN && + isADXOverThreshold; + bool isADXBullishPrev = isADXBiggerLastPrev && + isDXPBiggerThanDXNPrev && + isADXOverThresholdPrev; + bool isADXSwitchedToBullish = isADXBullish && + !isADXBullishPrev; + + // + bool isADXBearish = isADXLesserLast && + isDXNBiggerThanDXP && + isADXUnderThreshold; + bool isADXBearishPrev = isADXLesserLastPrev && + isDXNBiggerThanDXP && + isADXUnderThresholdPrev; + bool isADXSwitchedToBearish = isADXBearish && + !isADXBearishPrev; + + // + // ATR ... + + // + bool isATROverLast = conditions.atrBuffer[cIDX] > conditions.atrBuffer[pIDX]; + bool isATRUnderLast = conditions.atrBuffer[cIDX] < conditions.atrBuffer[pIDX]; + + // + // CCI ... + + // + bool isCCIBullish = conditions.cciBuffer[cIDX] > mInputs.cciReversalLevel; + bool isCCIBullishPrev = conditions.cciBuffer[pIDX] > mInputs.cciReversalLevel; + bool isCCISwitchedToBullish = isCCIBullish && + !isCCIBullishPrev; + + // + bool isCCIBearish = conditions.cciBuffer[cIDX] < mInputs.cciReversalLevel; + bool isCCIBearishPrev = conditions.cciBuffer[pIDX] < mInputs.cciReversalLevel; + bool isCCISwitchedToBearish = isCCIBearish && + !isCCIBearishPrev; + + // + bool isCCIOB = conditions.cciBuffer[cIDX] > mInputs.cciOBLevel; + bool isCCIOBPrev = conditions.cciBuffer[pIDX] > mInputs.cciOBLevel; + bool isCCICrossedOverOB = isCCIOB && + !isCCIOBPrev; + + // + bool isCCIUnderOB = conditions.cciBuffer[cIDX] < mInputs.cciOBLevel; + bool isCCIUnderOBPrev = conditions.cciBuffer[pIDX] < mInputs.cciOBLevel; + bool isCCICrossedUnderOB = isCCIUnderOB && + !isCCIUnderOBPrev; + + // + bool isCCIOS = conditions.cciBuffer[cIDX] < mInputs.cciOSLevel; + bool isCCIOSPrev = conditions.cciBuffer[pIDX] < mInputs.cciOSLevel; + bool isCCICrossedUnderOS = isCCIOS && + !isCCIOSPrev; + + // + bool isCCIOverOS = conditions.cciBuffer[cIDX] > mInputs.cciOSLevel; + bool isCCIOverOSPrev = conditions.cciBuffer[pIDX] > mInputs.cciOSLevel; + bool isCCICrossedOverOS = isCCIOverOS && + !isCCIOverOSPrev; + + // + // RSI ... + + // + bool isRSIBullish = conditions.rsiBuffer[cIDX] > mInputs.rsiReversalLevel; + bool isRSIBullishPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiReversalLevel; + bool isRSISwitchedToBullish = isRSIBullish && + !isRSIBullishPrev; + + // + bool isRSIBearish = conditions.rsiBuffer[cIDX] < mInputs.rsiReversalLevel; + bool isRSIBearishPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiReversalLevel; + bool isRSISwitchedToBearish = isRSIBearish && + !isRSIBearishPrev; + + // + bool isRSIOB = conditions.rsiBuffer[cIDX] > mInputs.rsiOBLevel; + bool isRSIOBPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiOBLevel; + bool isRSICrossedOverOB = isRSIOB && + !isRSIOBPrev; + + // + bool isRSIUnderOB = conditions.rsiBuffer[cIDX] < mInputs.rsiOBLevel; + bool isRSIUnderOBPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiOBLevel; + bool isRSICrossedUnderOB = isRSIUnderOB && + !isRSIUnderOBPrev; + + // + bool isRSIOS = conditions.rsiBuffer[cIDX] < mInputs.rsiOSLevel; + bool isRSIOSPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiOSLevel; + bool isRSICrossedUnderOS = isRSIOS && + !isRSIOSPrev; + + // + bool isRSIOverOS = conditions.rsiBuffer[cIDX] > mInputs.rsiOSLevel; + bool isRSIOverOSPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiOSLevel; + bool isRSICrossedOverOS = isRSIOverOS && + !isRSIOverOSPrev; + + // + // MFI ... + + // + bool isMFIBullish = conditions.mfiBuffer[cIDX] > mInputs.mfiReversalLevel; + bool isMFIBullishPrev = conditions.mfiBuffer[pIDX] > mInputs.mfiReversalLevel; + bool isMFISwitchedToBullish = isMFIBullish && + !isMFIBullishPrev; + + // + bool isMFIBearish = conditions.mfiBuffer[cIDX] < mInputs.mfiReversalLevel; + bool isMFIBearishPrev = conditions.mfiBuffer[pIDX] < mInputs.mfiReversalLevel; + bool isMFISwitchedToBearish = isMFIBearish && + !isMFIBearishPrev; + + // + bool isMFIOB = conditions.mfiBuffer[cIDX] > mInputs.mfiOBLevel; + bool isMFIOBPrev = conditions.mfiBuffer[pIDX] > mInputs.mfiOBLevel; + bool isMFICrossedOverOB = isMFIOB && + !isMFIOBPrev; + + // + bool isMFIUnderOB = conditions.mfiBuffer[cIDX] < mInputs.mfiOBLevel; + bool isMFIUnderOBPrev = conditions.mfiBuffer[pIDX] < mInputs.mfiOBLevel; + bool isMFICrossedUnderOB = isMFIUnderOB && + !isMFIUnderOBPrev; + + // + bool isMFIOS = conditions.mfiBuffer[cIDX] < mInputs.mfiOSLevel; + bool isMFIOSPrev = conditions.mfiBuffer[pIDX] < mInputs.mfiOSLevel; + bool isMFICrossedUnderOS = isMFIOS && + !isMFIOSPrev; + + // + bool isMFIOverOS = conditions.mfiBuffer[cIDX] > mInputs.mfiOSLevel; + bool isMFIOverOSPrev = conditions.mfiBuffer[pIDX] > mInputs.mfiOSLevel; + bool isMFICrossedOverOS = isMFIOverOS && + !isMFIOverOSPrev; + + // + // RVI ... + + // + bool isRVIBullish = conditions.rviBuffer[cIDX] > mInputs.rviBullishLevel; + bool isRVIBullishPrev = conditions.rviBuffer[pIDX] > mInputs.rviBullishLevel; + bool isRVISwitchedToBullish = isRVIBullish && + !isRVIBullishPrev; + + // + bool isRVIBearish = conditions.rviBuffer[cIDX] < mInputs.rviBearishLevel; + bool isRVIBearishPrev = conditions.rviBuffer[pIDX] < mInputs.rviBearishLevel; + bool isRVISwitchedToBearish = isRVIBearish && + !isRVIBearishPrev; + + // + bool isRVIOverSignal = conditions.rviBuffer[cIDX] > conditions.rviSignalBuffer[cIDX]; + bool isRVIOverSignalPrev = conditions.rviBuffer[pIDX] > conditions.rviSignalBuffer[pIDX]; + bool isRVICrossedOverSignal = isRVIOverSignal && + !isRVIOverSignalPrev; + + // + bool isRVIUnderSignal = conditions.rviBuffer[cIDX] < conditions.rviSignalBuffer[cIDX]; + bool isRVIUnderSignalPrev = conditions.rviBuffer[pIDX] < conditions.rviSignalBuffer[pIDX]; + bool isRVICrossedUnderSignal = isRVIUnderSignal && + !isRVIUnderSignalPrev; + + // + // MACD ... + + // + bool isMACDBullish = conditions.macdBuffer[cIDX] > mInputs.macdBullishLevel; + bool isMACDBullishPrev = conditions.macdBuffer[pIDX] > mInputs.macdBullishLevel; + bool isMACDSwitchedToBullish = isMACDBullish && + !isMACDBullishPrev; + + // + bool isMACDBearish = conditions.macdBuffer[cIDX] < mInputs.macdBearishLevel; + bool isMACDBearishPrev = conditions.macdBuffer[pIDX] < mInputs.macdBearishLevel; + bool isMACDSwitchedToBearish = isMACDBearish && + !isMACDBearishPrev; + + // + bool isMACDOverSignal = conditions.macdBuffer[cIDX] > conditions.macdSignalBuffer[cIDX]; + bool isMACDOverSignalPrev = conditions.macdBuffer[pIDX] > conditions.macdSignalBuffer[pIDX]; + bool isMACDCrossedOverSignal = isMACDOverSignal && + !isMACDOverSignalPrev; + + // + bool isMACDUnderSignal = conditions.macdBuffer[cIDX] < conditions.macdSignalBuffer[cIDX]; + bool isMACDUnderSignalPrev = conditions.macdBuffer[pIDX] < conditions.macdSignalBuffer[pIDX]; + bool isMACDCrossedUnderSignal = isMACDUnderSignal && + !isMACDUnderSignalPrev; + + // + // MOMENTUM ... + + // + bool isMomentumBullish = conditions.momentumBuffer[cIDX] > mInputs.momentumBullishLevel; + bool isMomentumBullishPrev = conditions.momentumBuffer[pIDX] > mInputs.momentumBullishLevel; + bool isMomentumSwitchedToBullish = isMomentumBullish && + !isMomentumBullishPrev; + + // + bool isMomentumBearish = conditions.momentumBuffer[cIDX] < mInputs.momentumBearishLevel; + bool isMomentumBearishPrev = conditions.momentumBuffer[pIDX] < mInputs.momentumBearishLevel; + bool isMomentumSwitchedToBearish = isMomentumBearish && + !isMomentumBearishPrev; + + // + // STOCHASTIC ... + + // + bool isStochasticBullish = conditions.stochasticBuffer[cIDX] > mInputs.stochasticReversalLevel; + bool isStochasticBullishPrev = conditions.stochasticBuffer[pIDX] > mInputs.stochasticReversalLevel; + bool isStochasticSwitchedToBullish = isStochasticBullish && + !isStochasticBullishPrev; + + // + bool isStochasticBearish = conditions.stochasticBuffer[cIDX] < mInputs.stochasticReversalLevel; + bool isStochasticBearishPrev = conditions.stochasticBuffer[pIDX] < mInputs.stochasticReversalLevel; + bool isStochasticSwitchedToBearish = isStochasticBearish && + !isStochasticBearishPrev; + + // + bool isStochasticOverSignal = conditions.stochasticBuffer[cIDX] > conditions.stochasticSignalBuffer[cIDX]; + bool isStochasticOverSignalPrev = conditions.stochasticBuffer[pIDX] > conditions.stochasticSignalBuffer[pIDX]; + bool isStochasticCrossedOverSignal = isStochasticOverSignal && + !isStochasticOverSignalPrev; + + // + bool isStochasticUnderSignal = conditions.stochasticBuffer[cIDX] < conditions.stochasticSignalBuffer[cIDX]; + bool isStochasticUnderSignalPrev = conditions.stochasticBuffer[pIDX] < conditions.stochasticSignalBuffer[pIDX]; + bool isStochasticCrossedUnderSignal = isStochasticUnderSignal && + !isStochasticUnderSignalPrev; + + // + bool isStochasticOB = conditions.stochasticBuffer[cIDX] > mInputs.stochasticOBLevel; + bool isStochasticOBPrev = conditions.stochasticBuffer[pIDX] > mInputs.stochasticOBLevel; + bool isStochasticCrossedOverOB = isStochasticOB && + !isStochasticOBPrev; + + // + bool isStochasticUnderOB = conditions.stochasticBuffer[cIDX] < mInputs.stochasticOBLevel; + bool isStochasticUnderOBPrev = conditions.stochasticBuffer[pIDX] < mInputs.stochasticOBLevel; + bool isStochasticCrossedUnderOB = isStochasticUnderOB && + !isStochasticUnderOBPrev; + + // + bool isStochasticOS = conditions.stochasticBuffer[cIDX] < mInputs.stochasticOSLevel; + bool isStochasticOSPrev = conditions.stochasticBuffer[pIDX] < mInputs.stochasticOSLevel; + bool isStochasticCrossedUnderOS = isStochasticOS && + !isStochasticOSPrev; + + // + bool isStochasticOverOS = conditions.stochasticBuffer[cIDX] > mInputs.stochasticOSLevel; + bool isStochasticOverOSPrev = conditions.stochasticBuffer[pIDX] > mInputs.stochasticOSLevel; + bool isStochasticCrossedOverOS = isStochasticOverOS && + !isStochasticOverOSPrev; + + // + // + // + + // + conditions.isCCIOB = isCCIOB; + conditions.isCCIOS = isCCIOS; + conditions.isRSIOB = isRSIOB; + conditions.isRSIOS = isRSIOS; + conditions.isMFIOB = isMFIOB; + conditions.isMFIOS = isMFIOS; + conditions.isACBullish = isACBullish; + conditions.isACBearish = isACBearish; + conditions.isACOverMax = isACOverMax; + conditions.isADOverMax = isADOverMax; + conditions.isACUnderMin = isACUnderMin; + conditions.isADUnderMin = isADUnderMin; + conditions.isADXBullish = isADXBullish; + conditions.isADXBearish = isADXBearish; + conditions.isCCIBullish = isCCIBullish; + conditions.isCCIBearish = isCCIBearish; + conditions.isRSIBullish = isRSIBullish; + conditions.isRSIBearish = isRSIBearish; + conditions.isMFIBullish = isMFIBullish; + conditions.isMFIBearish = isMFIBearish; + conditions.isRVIBullish = isRVIBullish; + conditions.isRVIBearish = isRVIBearish; + conditions.isATROverLast = isATROverLast; + conditions.isMACDBullish = isMACDBullish; + conditions.isMACDBearish = isMACDBearish; + conditions.isATRUnderLast = isATRUnderLast; + conditions.isADBiggerLast = isADBiggerLast; + conditions.isADLesserLast = isADLesserLast; + conditions.isStochasticOB = isStochasticOB; + conditions.isStochasticOS = isStochasticOS; + conditions.isADXBiggerLast = isADXBiggerLast; + conditions.isADXLesserLast = isADXLesserLast; + conditions.isRVIOverSignal = isRVIOverSignal; + conditions.isRVIUnderSignal = isRVIUnderSignal; + conditions.isMACDOverSignal = isMACDOverSignal; + conditions.isMACDUnderSignal = isMACDUnderSignal; + conditions.isMomentumBullish = isMomentumBullish; + conditions.isMomentumBearish = isMomentumBearish; + conditions.isADXOverThreshold = isADXOverThreshold; + conditions.isDXPBiggerThanDXN = isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = isDXNBiggerThanDXP; + conditions.isCCICrossedOverOB = isCCICrossedOverOB; + conditions.isCCICrossedOverOS = isCCICrossedOverOS; + conditions.isRSICrossedOverOB = isRSICrossedOverOB; + conditions.isRSICrossedOverOS = isRSICrossedOverOS; + conditions.isMFICrossedOverOB = isMFICrossedOverOB; + conditions.isMFICrossedOverOS = isMFICrossedOverOS; + conditions.isADXUnderThreshold = isADXUnderThreshold; + conditions.isCCICrossedUnderOB = isCCICrossedUnderOB; + conditions.isCCICrossedUnderOS = isCCICrossedUnderOS; + conditions.isRSICrossedUnderOB = isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = isRSICrossedUnderOS; + conditions.isMFICrossedUnderOB = isMFICrossedUnderOB; + conditions.isMFICrossedUnderOS = isMFICrossedUnderOS; + conditions.isStochasticBullish = isStochasticBullish; + conditions.isStochasticBearish = isStochasticBearish; + conditions.isACSwitchedToBullish = isACSwitchedToBullish; + conditions.isACSwitchedToBearish = isACSwitchedToBearish; + conditions.isADXSwitchedToBullish = isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = isADXSwitchedToBearish; + conditions.isCCISwitchedToBullish = isCCISwitchedToBullish; + conditions.isCCISwitchedToBearish = isCCISwitchedToBearish; + conditions.isRSISwitchedToBullish = isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = isRSISwitchedToBearish; + conditions.isMFISwitchedToBullish = isMFISwitchedToBullish; + conditions.isMFISwitchedToBearish = isMFISwitchedToBearish; + conditions.isRVISwitchedToBullish = isRVISwitchedToBullish; + conditions.isRVISwitchedToBearish = isRVISwitchedToBearish; + conditions.isRVICrossedOverSignal = isRVICrossedOverSignal; + conditions.isStochasticOverSignal = isStochasticOverSignal; + conditions.isStochasticUnderSignal = isStochasticUnderSignal; + conditions.isRVICrossedUnderSignal = isRVICrossedUnderSignal; + conditions.isMACDSwitchedToBullish = isMACDSwitchedToBullish; + conditions.isMACDSwitchedToBearish = isMACDSwitchedToBearish; + conditions.isMACDCrossedOverSignal = isMACDCrossedOverSignal; + conditions.isMACDCrossedUnderSignal = isMACDCrossedUnderSignal; + conditions.isStochasticCrossedOverOB = isStochasticCrossedOverOB; + conditions.isStochasticCrossedOverOS = isStochasticCrossedOverOS; + conditions.isStochasticCrossedUnderOB = isStochasticCrossedUnderOB; + conditions.isStochasticCrossedUnderOS = isStochasticCrossedUnderOS; + conditions.isMomentumSwitchedToBullish = isMomentumSwitchedToBullish; + conditions.isMomentumSwitchedToBearish = isMomentumSwitchedToBearish; + conditions.isStochasticSwitchedToBullish = isStochasticSwitchedToBullish; + conditions.isStochasticSwitchedToBearish = isStochasticSwitchedToBearish; + conditions.isStochasticCrossedOverSignal = isStochasticCrossedOverSignal; + conditions.isStochasticCrossedUnderSignal = isStochasticCrossedUnderSignal; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XOCSInputs mInputs; // Inputs ... + + // + // Buffers ... + double acBuffer[]; + double adBuffer[]; + double atrBuffer[]; + double cciBuffer[]; + double rsiBuffer[]; + double mfiBuffer[]; + double rviBuffer[]; + double adxBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double macdBuffer[]; + double momentumBuffer[]; + double rviSignalBuffer[]; + double macdSignalBuffer[]; + double stochasticBuffer[]; + double stochasticSignalBuffer[]; + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // AC ... + CopyBuffer( + mHandler, + X121_XOSCS_XAC_LINE, + barIndex, + maxRequiredBars, + acBuffer // + ); + + // + // AD ... + CopyBuffer( + mHandler, + X121_XOSCS_XAD_LINE, + barIndex, + maxRequiredBars, + adBuffer // + ); + + // + // ADX ... + CopyBuffer( + mHandler, + X121_XOSCS_XADX_LINE, + barIndex, + maxRequiredBars, + adxBuffer // + ); + + // + // ADX P ... + CopyBuffer( + mHandler, + X121_XOSCS_XADX_P_LINE, + barIndex, + maxRequiredBars, + adxpBuffer // + ); + + // + // ADX N ... + CopyBuffer( + mHandler, + X121_XOSCS_XADX_N_LINE, + barIndex, + maxRequiredBars, + adxnBuffer // + ); + + // + // ATR ... + CopyBuffer( + mHandler, + X121_XOSCS_XATR_LINE, + barIndex, + maxRequiredBars, + atrBuffer // + ); + + // + // CCI ... + CopyBuffer( + mHandler, + X121_XOSCS_XCCI_LINE, + barIndex, + maxRequiredBars, + cciBuffer // + ); + + // + // RSI ... + CopyBuffer( + mHandler, + X121_XOSCS_XRSI_LINE, + barIndex, + maxRequiredBars, + rsiBuffer // + ); + + // + // MFI ... + CopyBuffer( + mHandler, + X121_XOSCS_XMFI_LINE, + barIndex, + maxRequiredBars, + mfiBuffer // + ); + + // + // MOMENTUM ... + CopyBuffer( + mHandler, + X121_XOSCS_XMOMENTUM_LINE, + barIndex, + maxRequiredBars, + momentumBuffer // + ); + + // + // RVI ... + CopyBuffer( + mHandler, + X121_XOSCS_XRVI_LINE, + barIndex, + maxRequiredBars, + rviBuffer // + ); + + // + // RVI Signal ... + CopyBuffer( + mHandler, + X121_XOSCS_XRVI_S_LINE, + barIndex, + maxRequiredBars, + rviSignalBuffer // + ); + + // + // MACD ... + CopyBuffer( + mHandler, + X121_XOSCS_XMACD_LINE, + barIndex, + maxRequiredBars, + macdBuffer // + ); + + // + // MACD Signal ... + CopyBuffer( + mHandler, + X121_XOSCS_XMACD_S_LINE, + barIndex, + maxRequiredBars, + macdSignalBuffer // + ); + + // + // STOCHASTIC ... + CopyBuffer( + mHandler, + X121_XOSCS_XSTOCHASTIC_LINE, + barIndex, + maxRequiredBars, + stochasticBuffer // + ); + + // + // STOCHASTIC Signal ... + CopyBuffer( + mHandler, + X121_XOSCS_XSTOCHASTIC_S_LINE, + barIndex, + maxRequiredBars, + stochasticSignalBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + acBuffer, + maxAllowed // + ); + + // + CleanupArray( + adBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + cciBuffer, + maxAllowed // + ); + + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + mfiBuffer, + maxAllowed // + ); + + // + CleanupArray( + rviBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxpBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxnBuffer, + maxAllowed // + ); + + // + CleanupArray( + macdBuffer, + maxAllowed // + ); + + // + CleanupArray( + momentumBuffer, + maxAllowed // + ); + + // + CleanupArray( + rviSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + macdSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + stochasticBuffer, + maxAllowed // + ); + + // + CleanupArray( + stochasticSignalBuffer, + maxAllowed // + ); + } + + // +}; diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.x3ma.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.x3ma.mq5 new file mode 100644 index 0000000..e535571 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.x3ma.mq5 @@ -0,0 +1,788 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 X3MA +// Description: X3MA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 X3MA Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 X3MA" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Fast ... +input group "Fast"; +input int fastLength = 6; // Length +input ENUM_MA_METHOD fastMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE fastAppliedTo = PRICE_CLOSE; // Applied To + +// +// Medium ... +input group "Medium"; +input int mediumLength = 21; // Length +input ENUM_MA_METHOD mediumMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE mediumAppliedTo = PRICE_CLOSE; // Applied To + +// +// Slow ... +input group "Slow"; +input int slowLength = 34; // Length +input ENUM_MA_METHOD slowMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE slowAppliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool applyColor = false; + +// +input bool showFast = true; // Show Fast +input bool showMedium = true; // Show Medium +input bool showSlow = true; // Show Slow + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 3 + +// +// Plot Buffers ... + +// +// FAST ... + +// +#define fastBufferIndex 0 +double fastBuffer[]; + +// +#define fastColorBufferIndex 1 +double fastColorBuffer[]; + +// +#property indicator_label1 "X121 X3MA Fast" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrYellow, clrChocolate, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// MEDIUM ... + +// +#define mediumBufferIndex 2 +double mediumBuffer[]; + +// +#define mediumColorBufferIndex 3 +double mediumColorBuffer[]; + +// +#property indicator_label2 "X121 X3MA Medium" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style2 STYLE_DASHDOTDOT +#property indicator_width2 2 + +// +// SLOW ... + +// +#define slowBufferIndex 4 +double slowBuffer[]; + +// +#define slowColorBufferIndex 5 +double slowColorBuffer[]; + +// +#property indicator_label3 "X121 X3MA Slow" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_style3 STYLE_DASH +#property indicator_width3 2 + +// +// Data Buffers ... + +#define mLastBufferIndex 5 + +// +#define fastStateBufferIndex mLastBufferIndex + 1 +double fastStateBuffer[]; + +// +#define mediumStateBufferIndex mLastBufferIndex + 2 +double mediumStateBuffer[]; + +// +#define slowStateBufferIndex mLastBufferIndex + 3 +double slowStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int fastHandler = INVALID_HANDLE; +int mediumHandler = INVALID_HANDLE; +int slowHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // FAST ... + fastHandler = iMA( + _Symbol, + _Period, + fastLength, + 0, + fastMethod, + fastAppliedTo // + ); + bool isInited = fastHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MEDIUM ... + mediumHandler = iMA( + _Symbol, + _Period, + mediumLength, + 0, + mediumMethod, + mediumAppliedTo // + ); + isInited = mediumHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // SLOW ... + slowHandler = iMA( + _Symbol, + _Period, + slowLength, + 0, + slowMethod, + slowAppliedTo // + ); + isInited = slowHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(fastHandler); + IndicatorRelease(mediumHandler); + IndicatorRelease(slowHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // FAST ... + int fastCalculatedBars = BarsCalculated(fastHandler); + + // + // MEDIUM ... + int mediumCalculatedBars = BarsCalculated(mediumHandler); + + // + // SLOW ... + int slowCalculatedBars = BarsCalculated(slowHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // FAST ... + fastCalculatedBars >= maxLength && + // + // MEDIUM ... + mediumCalculatedBars >= maxLength && + // + // SLOW ... + slowCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // FAST ... + int copiedFasts = CopyBuffer(fastHandler, 0, 0, limit, fastBuffer); + + // + // MEDIUM ... + int copiedMediumss = CopyBuffer(mediumHandler, 0, 0, limit, mediumBuffer); + + // + // SLOW ... + int copiedSlows = CopyBuffer(slowHandler, 0, 0, limit, slowBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // FAST ... + copiedFasts >= limit && + // + // MEDIUM ... + copiedMediumss >= limit && + // + // SLOW ... + copiedSlows >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + fastLength > 2 && + mediumLength > 2 && + slowLength > 2 && + mediumLength > fastLength && + mediumLength < slowLength + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(fastLength, mediumLength); + result = MathMax(result, slowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // FAST ... + + // + ArraySetAsSeries(fastBuffer, true); + SetIndexBuffer(fastBufferIndex, fastBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fastBufferIndex, PLOT_SHOW_DATA, showFast); + + // + PlotIndexSetDouble(fastBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(fastColorBuffer, true); + SetIndexBuffer(fastColorBufferIndex, fastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIUM ... + + // + ArraySetAsSeries(mediumBuffer, true); + SetIndexBuffer(mediumBufferIndex, mediumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mediumBufferIndex, PLOT_SHOW_DATA, showMedium); + + // + PlotIndexSetDouble(mediumBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(mediumColorBuffer, true); + SetIndexBuffer(mediumColorBufferIndex, mediumColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SLOW ... + + // + ArraySetAsSeries(slowBuffer, true); + SetIndexBuffer(slowBufferIndex, slowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(slowBufferIndex, PLOT_SHOW_DATA, showSlow); + + // + PlotIndexSetDouble(slowBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(slowColorBuffer, true); + SetIndexBuffer(slowColorBufferIndex, slowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // FAST State ... + ArraySetAsSeries(fastStateBuffer, true); + SetIndexBuffer(fastStateBufferIndex, fastStateBuffer, INDICATOR_CALCULATIONS); + + // + // MEDIUM State ... + ArraySetAsSeries(mediumStateBuffer, true); + SetIndexBuffer(mediumStateBufferIndex, mediumStateBuffer, INDICATOR_CALCULATIONS); + + // + // SLOW State ... + ArraySetAsSeries(slowStateBuffer, true); + SetIndexBuffer(slowStateBufferIndex, slowStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // FAST ... + fastBuffer[barIndex] = emptyValue; + fastColorBuffer[barIndex] = hideColorIDX; + fastStateBuffer[barIndex] = neuturalState; + + // + // MEDIUM ... + mediumBuffer[barIndex] = emptyValue; + mediumColorBuffer[barIndex] = hideColorIDX; + mediumStateBuffer[barIndex] = neuturalState; + + // + // SLOW ... + slowBuffer[barIndex] = emptyValue; + slowColorBuffer[barIndex] = hideColorIDX; + slowStateBuffer[barIndex] = neuturalState; +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == ratesTotal; + + // + double iLow = low[bar_index]; + double iHigh = high[bar_index]; + double iClose = close[bar_index]; + + // + // FAST ... + + // + double iFast = fastBuffer[bar_index]; + + // + double iFastState = + iLow > iFast + ? bullishState + : iHigh < iFast + ? bearishState + : neuturalState; + double iFastColor = hideColorIDX; + if (showFast) + { + // + if (applyColor) + { + // + iFastColor = + iFastState == bullishState + ? bullishColorIDX + : iFastState == bearishState + ? bearishColorIDX + : neuturalColorIDX; + } + else + { + iFastColor = bullishColorIDX; + } + } + fastColorBuffer[bar_index] = iFastColor; + fastStateBuffer[bar_index] = iFastState; + + // + // MEDIUM ... + + // + double iMedium = mediumBuffer[bar_index]; + + // + double iMediumState = + iLow > iMedium + ? bullishState + : iHigh < iMedium + ? bearishState + : neuturalState; + double iMediumColor = hideColorIDX; + if (showMedium) + { + // + if (applyColor) + { + // + iMediumColor = + iMediumState == bullishState + ? bullishColorIDX + : iMediumState == bearishState + ? bearishColorIDX + : neuturalColorIDX; + } + else + { + iMediumColor = bullishColorIDX; + } + } + mediumColorBuffer[bar_index] = iMediumColor; + mediumStateBuffer[bar_index] = iMediumState; + + // + // SLOW ... + + // + double iSlow = slowBuffer[bar_index]; + + // + double iSlowState = + iLow > iSlow + ? bullishState + : iHigh < iSlow + ? bearishState + : neuturalState; + double iSlowColor = hideColorIDX; + if (showSlow) + { + // + if (applyColor) + { + // + iSlowColor = + iSlowState == bullishState + ? bullishColorIDX + : iSlowState == bearishState + ? bearishColorIDX + : neuturalColorIDX; + } + else + { + iSlowColor = bullishColorIDX; + } + } + slowColorBuffer[bar_index] = iSlowColor; + slowStateBuffer[bar_index] = iSlowState; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xatr.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xatr.mq5 new file mode 100644 index 0000000..08dbc82 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xatr.mq5 @@ -0,0 +1,882 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XATR +// Description: XATR ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XATR Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XATR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "RSI Detection"; +input int rsiLength = 14; // Length +input ENUM_X_PRICE rsiPriceType = X_PRICE_CLOSE; // Applied To +input ENUM_X_MA_METHOD rsiSmoothingMethod = X_MA_MODE_SMA; // Smoothing Method; + +// +input group "ATR Detection"; +input int atrLength = 14; // Length +input double atrMultiplier = 1; // Multiplier +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // Upper Zone Applied To +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // Lower Zone Applied To +input ENUM_X_MA_METHOD atrSmoothingMethod = X_MA_MODE_SMA; // Smoothing Method + +// +input group "Price Change"; +input int priceChangeSmoothingLength = 14; // Length +input ENUM_X_PRICE priceChangeType = X_PRICE_CLOSE; // Price Type +input ENUM_X_MA_METHOD priceChangeSmoothingMethod = X_MA_MODE_SMA; // Moving Average Moethod + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showAtrUpper = true; // Show Upper Zone +input bool showAtrLower = true; // Show Lower Zone +input bool showSmoothedAtrUpper = true; // Show Smoothed Upper Zone +input bool showSmoothedAtrLower = true; // Show Smoothed Lower Zone +input bool showRSIChange = true; // Show RSI Change +input bool showSmoothedRSIChange = true; // ShowSmoothed RSI Change +input bool showPriceChange = true; // Show Price Change +input bool showSmoothedPriceChange = true; // ShowSmoothed Price Change + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 8 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 0 +double atrUpperBuffer[]; + +#property indicator_label1 "X121 ATRU" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 1 +double atrLowerBuffer[]; + +#property indicator_label2 "X121 ATRL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrYellow +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// ATR Smoothed ... + +// +// Upper ... + +// +#define atrSmoothedUpperBufferIndex 2 +double atrSmoothedUpperBuffer[]; + +#property indicator_label3 "X121 ATRUSM" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrYellow +#property indicator_style3 STYLE_DASH +#property indicator_width3 1 + +// +// Lower ... + +// +#define atrSmoothedLowerBufferIndex 3 +double atrSmoothedLowerBuffer[]; + +#property indicator_label4 "X121 ATRLSM" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrYellow +#property indicator_style4 STYLE_DASH +#property indicator_width4 1 + +// +// Price Change ... + +// +#define priceChangeBufferIndex 4 +double priceChangeBuffer[]; + +#property indicator_label5 "X121 PCH" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrOrchid +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +// Price Change Smoothed ... + +// +#define priceChangeSmoothedBufferIndex 5 +double priceChangeSmoothedBuffer[]; + +#property indicator_label6 "X121 PCHSM" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrOrchid +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// RSI Change ... + +// +#define rsiChangeBufferIndex 6 +double rsiChangeBuffer[]; + +#property indicator_label7 "X121 RSICH" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCornflowerBlue +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// RSI Change Smoothed ... + +// +#define rsiChangeSmoothedBufferIndex 7 +double rsiChangeSmoothedBuffer[]; + +#property indicator_label8 "X121 RSICHSM" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCornflowerBlue +#property indicator_style8 STYLE_SOLID +#property indicator_width8 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 7; + +// +// ATR ... + +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +// RSI ... +#define rsiBufferIndex mLastBufferIndex + 2 +double rsiBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// RSI Handler ... +int rsiHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +ENUM_APPLIED_PRICE rsiAppliedTo = ToAppliedPrice(rsiPriceType); + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + bool isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(rsiHandler); + IndicatorRelease(atrHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + } + + // + // Validate Calculated Bars ... + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // RSI ... + int copiedRsis = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, limit, atrBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // RSI ... + copiedRsis > 0 && + // + // ATR ... + copiedAtrs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + // RSI ... + rsiLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 && + // + priceChangeSmoothingLength > 0 && + // + IsValid(rsiPriceType) && + IsValid(priceChangeType) && + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(rsiLength, atrLength); + result = MathMax(result, priceChangeSmoothingLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // ATR ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showAtrUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrUpperBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrUpperBufferIndex, PLOT_SHOW_DATA, showAtrUpper); + PlotIndexSetInteger(atrUpperBufferIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showAtrLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrLowerBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrLowerBufferIndex, PLOT_SHOW_DATA, showAtrLower); + PlotIndexSetInteger(atrLowerBufferIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // ATR Smoothed ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrSmoothedUpperDrawType = showSmoothedAtrUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrSmoothedUpperBuffer, true); + SetIndexBuffer(atrSmoothedUpperBufferIndex, atrSmoothedUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrSmoothedUpperBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrSmoothedUpperBufferIndex, PLOT_SHOW_DATA, showSmoothedAtrUpper); + PlotIndexSetInteger(atrSmoothedUpperBufferIndex, PLOT_DRAW_TYPE, atrSmoothedUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrSmoothedLowerDrawType = showSmoothedAtrLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrSmoothedLowerBuffer, true); + SetIndexBuffer(atrSmoothedLowerBufferIndex, atrSmoothedLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrSmoothedLowerBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrSmoothedLowerBufferIndex, PLOT_SHOW_DATA, showSmoothedAtrLower); + PlotIndexSetInteger(atrSmoothedLowerBufferIndex, PLOT_DRAW_TYPE, atrSmoothedLowerDrawType); + + // + // PriceChange ... + ENUM_DRAW_TYPE priceChangeDrawType = showPriceChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(priceChangeBuffer, true); + SetIndexBuffer(priceChangeBufferIndex, priceChangeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(priceChangeBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(priceChangeBufferIndex, PLOT_SHOW_DATA, showPriceChange); + PlotIndexSetInteger(priceChangeBufferIndex, PLOT_DRAW_TYPE, priceChangeDrawType); + + // + // PriceChange Smoothed ... + ENUM_DRAW_TYPE priceChangeSmoothedaDrawType = showSmoothedPriceChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(priceChangeSmoothedBuffer, true); + SetIndexBuffer(priceChangeSmoothedBufferIndex, priceChangeSmoothedBuffer, INDICATOR_DATA); + PlotIndexSetDouble(priceChangeSmoothedBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(priceChangeSmoothedBufferIndex, PLOT_SHOW_DATA, showSmoothedPriceChange); + PlotIndexSetInteger(priceChangeSmoothedBufferIndex, PLOT_DRAW_TYPE, priceChangeSmoothedaDrawType); + + // + // RSIChange ... + ENUM_DRAW_TYPE rsiChangeDrawType = showRSIChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(rsiChangeBuffer, true); + SetIndexBuffer(rsiChangeBufferIndex, rsiChangeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(rsiChangeBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rsiChangeBufferIndex, PLOT_SHOW_DATA, showRSIChange); + PlotIndexSetInteger(rsiChangeBufferIndex, PLOT_DRAW_TYPE, rsiChangeDrawType); + + // + // RSIChangeMa ... + ENUM_DRAW_TYPE rsiChangeMaDrawType = showSmoothedRSIChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(rsiChangeSmoothedBuffer, true); + SetIndexBuffer(rsiChangeSmoothedBufferIndex, rsiChangeSmoothedBuffer, INDICATOR_DATA); + PlotIndexSetDouble(rsiChangeSmoothedBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rsiChangeSmoothedBufferIndex, PLOT_SHOW_DATA, showSmoothedRSIChange); + PlotIndexSetInteger(rsiChangeSmoothedBufferIndex, PLOT_DRAW_TYPE, rsiChangeMaDrawType); + + // + // Data Buffers ... + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); + IndicatorSetInteger(INDICATOR_DIGITS, 2); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateAtrZones( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + rsiBuffer[barIndex] = 0; + atrBuffer[barIndex] = 0; + atrUpperBuffer[barIndex] = 0; + atrLowerBuffer[barIndex] = 0; + rsiChangeBuffer[barIndex] = 0; + priceChangeBuffer[barIndex] = 0; + atrSmoothedUpperBuffer[barIndex] = 0; + atrSmoothedLowerBuffer[barIndex] = 0; + rsiChangeSmoothedBuffer[barIndex] = 0; + priceChangeSmoothedBuffer[barIndex] = 0; +} + +/** + * Calculate ATR Zones ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateAtrZones( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + double points = GetPoints(_Symbol); + + // + // ATR Calculations ... + double iAtr = atrBuffer[bar_index]; + double iMultiPliedAtr = iAtr * atrMultiplier; + + // + // Select Upper Price ... + double iUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + // Select Lower Price ... + double iLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + // Calculate Atrs ... + + // + double iAtrUpper = iUpperPrice + iMultiPliedAtr; + double iAtrLower = iLowerPrice - iMultiPliedAtr; + + // + atrUpperBuffer[bar_index] = iAtrUpper; + atrLowerBuffer[bar_index] = iAtrLower; + + // + bool canSmoothAtr = atrSmoothingMethod != X_MA_MODE_NONE; + if (canSmoothAtr) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrUpperBuffer, + atrSmoothedUpperBuffer, + atrSmoothingMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrLowerBuffer, + atrSmoothedLowerBuffer, + atrSmoothingMethod // + ); + } + else + { + // + atrSmoothedUpperBuffer[bar_index] = iAtrUpper; + atrSmoothedLowerBuffer[bar_index] = iAtrLower; + } + + // + // RSI Change Calculations ... + + // + double iRsi = rsiBuffer[bar_index]; + double iRsiP = rsiBuffer[bar_index + 1]; + double iRsiPrice = GetAppliedPrice( + rsiPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + double iRsiChanged = iRsi - iRsiP; + double iRsiPointsChanged = iRsiChanged / points; + + // + double iRChange = iRsiPrice + (iRsiChanged * points); + rsiChangeBuffer[bar_index] = iRChange; + + // + bool canSmoothRsi = rsiSmoothingMethod != X_MA_MODE_NONE; + if (canSmoothRsi) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + rsiChangeBuffer, + rsiChangeSmoothedBuffer, + rsiSmoothingMethod // + ); + } + else + { + rsiChangeSmoothedBuffer[bar_index] = iRChange; + } + + // + // PRICE Change Calculation ... + + // + double iPChangePrice = GetAppliedPrice( + priceChangeType, + open, + high, + low, + close, + bar_index // + ); + double iPPChangePrice = GetAppliedPrice( + priceChangeType, + open, + high, + low, + close, + bar_index + 1 // + ); + + // + double iPriceChange = iPChangePrice - iPPChangePrice; + double iPricePointsChanged = iPriceChange / points; + double iVolatilityChange = iPriceChange / iAtr; + + // + double iPChange = iPChangePrice + (iPricePointsChanged * points); + priceChangeBuffer[bar_index] = iPChange; + + // + bool canSmoothPriceChange = priceChangeSmoothingMethod != X_MA_MODE_NONE; + if (canSmoothPriceChange) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + priceChangeBuffer, + priceChangeSmoothedBuffer, + priceChangeSmoothingMethod // + ); + } + else + { + priceChangeSmoothedBuffer[bar_index] = iPChange; + } +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xca.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xca.mq5 new file mode 100644 index 0000000..7e1ec60 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xca.mq5 @@ -0,0 +1,2601 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCA +// Description: XCA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCA Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCA" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Boundary Detection"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Fibo Levels"; +input ENUM_X_FIBO_LEVELS fiboLevel1 = X_FIBO_LEVEL_236; // Fibo Level 1 +input ENUM_X_FIBO_LEVELS fiboLevel2 = X_FIBO_LEVEL_382; // Fibo Level 2 +input ENUM_X_FIBO_LEVELS fiboLevel3 = X_FIBO_LEVEL_500; // Fibo Level 3 +input ENUM_X_FIBO_LEVELS fiboLevel4 = X_FIBO_LEVEL_618; // Fibo Level 4 +input ENUM_X_FIBO_LEVELS fiboLevel5 = X_FIBO_LEVEL_764; // Fibo Level 5 + +// +input group "Sar Detection"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +// KI ... +input group "KI"; +input int kiLength = 26; // KI Length + +// +// VIDYA ... +// Variable Index Dynamic Average ... +input group "VIDYA"; +input int vidyaCMOLength = 20; // CMO (Candle Momentum) Length +input int vidyaEMALength = 14; // EMA Length +input ENUM_APPLIED_PRICE vidyaAppliedTo = PRICE_CLOSE; // Applied To + +// +// Manalyser ... +input group "Manalyser"; +input int manalyserLength = 14; // Length +input ENUM_MA_METHOD manalyserMethod = MODE_SMA; // Method + +// +input group "Swing Detection"; +input int swingLength = 5; // Length + +// +input group "Support and Resistance"; +input int supResSmoothingLength = 7; // Smoothing Length +input ENUM_X_MA_METHOD supResSmoothingMode = X_MA_MODE_NONE; // Smoothing Method + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showSar = true; // Show Sar +input bool showKI = true; // Show KI +input bool showTKI = true; // Show KI Trend +input bool showMAH = true; // Show MAH +input bool showMAL = true; // Show MAL +input bool showMAC = true; // Show MAC +input bool showVidya = true; // Show Vidya +input bool showTrend = true; // Show Trend +input bool showSwings = true; // Show Swings +input bool showFiboLevel1 = true; // Show Fibo Level 1 +input bool showFiboLevel2 = true; // Show Fibo Level 2 +input bool showFiboLevel3 = true; // Show Fibo Level 3 +input bool showFiboLevel4 = true; // Show Fibo Level 4 +input bool showFiboLevel5 = true; // Show Fibo Level 5 +input bool showPeaksAndVales = true; // Show Peaks And Vales +input bool showPeakAndValeGolden = true; // Show Peak and Vale Golden +input bool showSupportAndResistance = true; // Show Support and Resistance + +// +bool showShortCycle = false; // Show Short Cycle +bool showMediumCycle = false; // Show Medium Cycle +bool showLongCycle = false; // Show Long Cycle +bool showHindCycle = false; // Show Hind Cycle + +// +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +int swingLowArrowCode = 225; // Swing Low Arrow Code +int swingHighArrowCode = 226; // Swing High Arrow Code + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 39 +#property indicator_plots 29 + +// +// Plot Buffers ... + +// +// SHORT ... + +// +#define sHHBufferIndex 0 +double sHHBuffer[]; + +// +#property indicator_label1 "SH" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrGray +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +#define sLLBufferIndex 1 +double sLLBuffer[]; + +// +#property indicator_label2 "SL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrGray +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 2 +double mHHBuffer[]; + +// +#property indicator_label3 "MH" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrIndigo +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define mLLBufferIndex 3 +double mLLBuffer[]; + +// +#property indicator_label4 "ML" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrIndigo +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// LONG ... + +// +#define lHHBufferIndex 4 +double lHHBuffer[]; + +// +#property indicator_label5 "LH" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrGoldenrod +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +#define lLLBufferIndex 5 +double lLLBuffer[]; + +// +#property indicator_label6 "LL" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrGoldenrod +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +// HIND ... + +// +#define hHHBufferIndex 6 +double hHHBuffer[]; + +// +#property indicator_label7 "HH" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +#define hLLBufferIndex 7 +double hLLBuffer[]; + +// +#property indicator_label8 "HL" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrBrown +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// SUPPORT ... + +// +#define supportBufferIndex 8 +double supportBuffer[]; + +// +#property indicator_label9 "SUPPORT" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrLime +#property indicator_style9 STYLE_SOLID +#property indicator_width9 1 + +// +// RESISTANCE ... + +// +#define resistanceBufferIndex 9 +double resistanceBuffer[]; + +// +#property indicator_label10 "RESISTANCE" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrRed +#property indicator_style10 STYLE_SOLID +#property indicator_width10 1 + +// +// PEAKS ... + +// +#define peakBufferIndex 10 +double peakBuffer[]; + +// +#property indicator_label11 "PEAK" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrMagenta +#property indicator_width11 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 11 +double peakGoldenBuffer[]; + +// +#property indicator_label12 "PEAK Golden" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width12 1 + +// +// VALES ... + +// +#define valeBufferIndex 12 +double valeBuffer[]; + +// +#property indicator_label13 "VALE" +#property indicator_type13 DRAW_ARROW +#property indicator_color13 clrAqua +#property indicator_width13 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 13 +double valeGoldenBuffer[]; + +// +#property indicator_label14 "VALES Golden" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrAqua +#property indicator_style4 STYLE_DOT +#property indicator_width14 1 + +// +// FIBO Level 1 + +// +#define fiboLevel1BufferIndex 14 +double fiboLevel1Buffer[]; + +// +#property indicator_label15 "Fibo L1" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGold +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +// FIBO Level 2 + +// +#define fiboLevel2BufferIndex 15 +double fiboLevel2Buffer[]; + +// +#property indicator_label16 "Fibo L2" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGold +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// FIBO Level 3 + +// +#define fiboLevel3BufferIndex 16 +double fiboLevel3Buffer[]; + +// +#property indicator_label17 "Fibo L3" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrYellow +#property indicator_style17 STYLE_DASH +#property indicator_width17 1 + +// +// FIBO Level 4 + +// +#define fiboLevel4BufferIndex 17 +double fiboLevel4Buffer[]; + +// +#property indicator_label18 "Fibo L4" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrGold +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// FIBO Level 5 + +// +#define fiboLevel5BufferIndex 18 +double fiboLevel5Buffer[]; + +// +#property indicator_label19 "Fibo L5" +#property indicator_type19 DRAW_LINE +#property indicator_color19 clrGold +#property indicator_style19 STYLE_DOT +#property indicator_width19 1 + +// +// SAR ... + +// +#define sarBufferIndex 19 +double sarBuffer[]; + +// +#property indicator_label20 "SAR" +#property indicator_type20 DRAW_ARROW +#property indicator_color20 clrYellow +#property indicator_width20 1 + +// +// TREND ... + +// +#define trendBufferIndex 20 +#define trendBufferPlotIndex 20 +double trendBuffer[]; + +// +#define trendColorBufferIndex 21 +double trendColorBuffer[]; + +// +#property indicator_label21 "TRND" +#property indicator_type21 DRAW_COLOR_LINE +#property indicator_color21 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style21 STYLE_DASH +#property indicator_width21 2 + +// +// KI ... + +// +#define kiBufferIndex 22 +#define kiBufferPlotIndex 21 +double kiBuffer[]; + +// +#define kiColorBufferIndex 23 +double kiColorBuffer[]; + +// +#property indicator_label22 "KI" +#property indicator_type22 DRAW_COLOR_LINE +#property indicator_color22 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style22 STYLE_DASHDOTDOT +#property indicator_width22 2 + +// +// SWING Low ... + +// +#define swingLowBufferIndex 24 +#define swingLowBufferPlotIndex 22 +double swingLowBuffer[]; + +// +#property indicator_label23 "SWL" +#property indicator_type23 DRAW_ARROW +#property indicator_color23 clrGreen +#property indicator_width23 1 + +// +// SWING High ... + +// +#define swingHighBufferIndex 25 +#define swingHighBufferPlotIndex 23 +double swingHighBuffer[]; + +// +#property indicator_label24 "SWH" +#property indicator_type24 DRAW_ARROW +#property indicator_color24 clrRed +#property indicator_width24 1 + +// +// TKI ... + +// +#define tkiBufferIndex 26 +#define tkiBufferPlotIndex 24 +double tkiBuffer[]; + +// +#define tkiColorBufferIndex 27 +double tkiColorBuffer[]; + +// +#property indicator_label25 "TKI" +#property indicator_type25 DRAW_COLOR_LINE +#property indicator_color25 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style25 STYLE_DASHDOTDOT +#property indicator_width25 2 + +// +// VIDYA ... + +// +#define vidyaBufferIndex 28 +#define vidyaBufferPlotIndex 25 +double vidyaBuffer[]; + +// +#define vidyaColorBufferIndex 29 +double vidyaColorBuffer[]; + +// +#property indicator_label26 "VIDYA" +#property indicator_type26 DRAW_COLOR_LINE +#property indicator_color26 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style26 STYLE_SOLID +#property indicator_width26 1 + +// +// MAH ... + +// +#define mahBufferIndex 30 +#define mahBufferPlotIndex 26 +double mahBuffer[]; + +// +#property indicator_label27 "MAH" +#property indicator_type27 DRAW_LINE +#property indicator_color27 clrMagenta +#property indicator_style27 STYLE_SOLID +#property indicator_width27 1 + +// +// MAL ... + +// +#define malBufferIndex 31 +#define malBufferPlotIndex 27 +double malBuffer[]; + +// +#property indicator_label28 "MAL" +#property indicator_type28 DRAW_LINE +#property indicator_color28 clrAqua +#property indicator_style28 STYLE_SOLID +#property indicator_width28 1 + +// +// MAC ... + +// +#define macBufferIndex 32 +#define macBufferPlotIndex 28 +double macBuffer[]; + +// +#property indicator_label29 "MAC" +#property indicator_type29 DRAW_LINE +#property indicator_color29 clrYellow +#property indicator_style29 STYLE_SOLID +#property indicator_width29 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 32 + +// +#define trendStateBufferIndex mLastBufferIndex + 1 +double trendStateBuffer[]; + +// +#define kiStateBufferIndex mLastBufferIndex + 2 +double kiStateBuffer[]; + +// +#define tkiStateBufferIndex mLastBufferIndex + 3 +double tkiStateBuffer[]; + +// +#define vidyaStateBufferIndex mLastBufferIndex + 4 +double vidyaStateBuffer[]; + +// +#define supBufferIndex mLastBufferIndex + 5 +double supBuffer[]; + +// +#define resBufferIndex mLastBufferIndex + 6 +double resBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int firstBarIndex; + +// +int maxLength; + +// +// SAR Handler ... +int sarHandler = INVALID_HANDLE; + +// +// TREND Handler ... +int tkiHandler = INVALID_HANDLE; +int vidyaHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +// Manalyser Handlers ... +int mahHandler = INVALID_HANDLE; +int malHandler = INVALID_HANDLE; +int macHandler = INVALID_HANDLE; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TKI ... + tkiHandler = iMA( + _Symbol, + _Period, + kiLength, + 0, + MODE_SMA, + PRICE_MEDIAN // + ); + isInited = tkiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // VIDYA ... + vidyaHandler = iVIDyA( + _Symbol, + _Period, + vidyaCMOLength, + vidyaEMALength, + 0, + vidyaAppliedTo // + ); + isInited = vidyaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mHCLength, + 0, + MODE_SMA, + PRICE_CLOSE // + ); + isInited = trendHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MANALYSE ... + + // + // MAH ... + mahHandler = iMA( + _Symbol, + _Period, + manalyserLength, + 0, + manalyserMethod, + PRICE_HIGH // + ); + isInited = mahHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MAL ... + malHandler = iMA( + _Symbol, + _Period, + manalyserLength, + 0, + manalyserMethod, + PRICE_LOW // + ); + isInited = malHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MAC ... + macHandler = iMA( + _Symbol, + _Period, + manalyserLength, + 0, + manalyserMethod, + PRICE_CLOSE // + ); + isInited = macHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(sarHandler); + IndicatorRelease(tkiHandler); + IndicatorRelease(vidyaHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // TKI ... + int tkiCalculatedBars = BarsCalculated(tkiHandler); + + // + // VIDYA ... + int vidyaCalculatedBars = BarsCalculated(vidyaHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + // MANALYSER ... + + // + // MAH ... + int mahCalculatedBars = BarsCalculated(mahHandler); + + // + // MAL ... + int malCalculatedBars = BarsCalculated(malHandler); + + // + // MAC ... + int macCalculatedBars = BarsCalculated(macHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // TKI ... + tkiCalculatedBars >= maxLength && + // + // VIDYA ... + vidyaCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength && + // + // MANALYSER ... + // MAH ... + mahCalculatedBars >= maxLength && + // MAL ... + malCalculatedBars >= maxLength && + // MAC ... + macCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + + // + // TKI ... + int copiedTKIs = CopyBuffer(tkiHandler, 0, 0, limit, tkiBuffer); + + // + // TKI ... + int copiedVidyas = CopyBuffer(vidyaHandler, 0, 0, limit, vidyaBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit + 1, trendBuffer); + + // + // MANALYSER ... + + // + // MAH ... + int copiedMahs = CopyBuffer(mahHandler, 0, 0, limit, mahBuffer); + + // + // MAL ... + int copiedMals = CopyBuffer(malHandler, 0, 0, limit, malBuffer); + + // + // MAC ... + int copiedMacs = CopyBuffer(macHandler, 0, 0, limit, macBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // SAR ... + copiedSars >= limit && + // + // TKI ... + copiedTKIs >= limit && + // + // VIDYA ... + copiedVidyas >= limit && + // + // TREND ... + copiedTrends >= limit && + // + // MANALYSER ... + // MAH ... + copiedMahs >= limit && + // MAL ... + copiedMals >= limit && + // MAC ... + copiedMacs >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + kiLength > 0 && + swingLength > 0 && + sarMax > sarStep && + vidyaEMALength > 0 && + vidyaCMOLength > 0 && + manalyserLength > 0 && + // + // XCA ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(kiLength, swingLength); + result = MathMax(result, vidyaCMOLength); + result = MathMax(result, vidyaEMALength); + result = MathMax(result, manalyserLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferIndex, PLOT_DRAW_TYPE, sDrawType); + + // + PlotIndexSetDouble(sHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferIndex, PLOT_DRAW_TYPE, sDrawType); + + // + PlotIndexSetDouble(sLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferIndex, PLOT_DRAW_TYPE, mDrawType); + + // + PlotIndexSetDouble(mHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferIndex, PLOT_DRAW_TYPE, mDrawType); + + // + PlotIndexSetDouble(mLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferIndex, PLOT_DRAW_TYPE, lDrawType); + + // + PlotIndexSetDouble(lHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferIndex, PLOT_DRAW_TYPE, lDrawType); + + // + PlotIndexSetDouble(lLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferIndex, PLOT_DRAW_TYPE, hDrawType); + + // + PlotIndexSetDouble(hHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferIndex, PLOT_DRAW_TYPE, hDrawType); + + // + PlotIndexSetDouble(hLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // SUPPORT / RESISTANCE ... + + // + ENUM_DRAW_TYPE supResDrawType = showSupportAndResistance ? DRAW_LINE : DRAW_NONE; + + // + // SUPPORT ... + + // + ArraySetAsSeries(supportBuffer, true); + SetIndexBuffer(supportBufferIndex, supportBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(supportBufferIndex, PLOT_SHOW_DATA, showSupportAndResistance); + PlotIndexSetInteger(supportBufferIndex, PLOT_DRAW_TYPE, supResDrawType); + + // + PlotIndexSetDouble(supportBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // RESISTANCE ... + + // + ArraySetAsSeries(resistanceBuffer, true); + SetIndexBuffer(resistanceBufferIndex, resistanceBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(resistanceBufferIndex, PLOT_SHOW_DATA, showSupportAndResistance); + PlotIndexSetInteger(resistanceBufferIndex, PLOT_DRAW_TYPE, supResDrawType); + + // + PlotIndexSetDouble(resistanceBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peakBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valeBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPeakAndValeGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferIndex, PLOT_SHOW_DATA, showPeakAndValeGolden); + PlotIndexSetInteger(peakGoldenBufferIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferIndex, PLOT_SHOW_DATA, showPeakAndValeGolden); + PlotIndexSetInteger(valeGoldenBufferIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L1 ... + + // + ENUM_DRAW_TYPE fiboL1DrawType = showFiboLevel1 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel1Buffer, true); + SetIndexBuffer(fiboLevel1BufferIndex, fiboLevel1Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel1BufferIndex, PLOT_SHOW_DATA, showFiboLevel1); + PlotIndexSetInteger(fiboLevel1BufferIndex, PLOT_DRAW_TYPE, fiboL1DrawType); + + // + PlotIndexSetDouble(fiboLevel1BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L2 ... + + // + ENUM_DRAW_TYPE fiboL2DrawType = showFiboLevel2 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel2Buffer, true); + SetIndexBuffer(fiboLevel2BufferIndex, fiboLevel2Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel2BufferIndex, PLOT_SHOW_DATA, showFiboLevel2); + PlotIndexSetInteger(fiboLevel2BufferIndex, PLOT_DRAW_TYPE, fiboL2DrawType); + + // + PlotIndexSetDouble(fiboLevel2BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L3 ... + + // + ENUM_DRAW_TYPE fiboL3DrawType = showFiboLevel3 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel3Buffer, true); + SetIndexBuffer(fiboLevel3BufferIndex, fiboLevel3Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel3BufferIndex, PLOT_SHOW_DATA, showFiboLevel3); + PlotIndexSetInteger(fiboLevel3BufferIndex, PLOT_DRAW_TYPE, fiboL3DrawType); + + // + PlotIndexSetDouble(fiboLevel3BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L4 ... + + // + ENUM_DRAW_TYPE fiboL4DrawType = showFiboLevel4 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel4Buffer, true); + SetIndexBuffer(fiboLevel4BufferIndex, fiboLevel4Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel4BufferIndex, PLOT_SHOW_DATA, showFiboLevel4); + PlotIndexSetInteger(fiboLevel4BufferIndex, PLOT_DRAW_TYPE, fiboL4DrawType); + + // + PlotIndexSetDouble(fiboLevel4BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L5 ... + + // + ENUM_DRAW_TYPE fiboL5DrawType = showFiboLevel5 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel5Buffer, true); + SetIndexBuffer(fiboLevel5BufferIndex, fiboLevel5Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel5BufferIndex, PLOT_SHOW_DATA, showFiboLevel5); + PlotIndexSetInteger(fiboLevel5BufferIndex, PLOT_DRAW_TYPE, fiboL5DrawType); + + // + PlotIndexSetDouble(fiboLevel5BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // SAR ... + + // + ENUM_DRAW_TYPE sarDrawType = showSar ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetInteger(sarBufferIndex, PLOT_DRAW_TYPE, sarDrawType); + + // + PlotIndexSetDouble(sarBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferIndex, PLOT_ARROW, sarArrowCode); + + // + // TREND ... + + // + ENUM_DRAW_TYPE trendDrawType = showTrend ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + // PlotIndexSetInteger(trendBufferPlotIndex, PLOT_DRAW_TYPE, trendDrawType); + + // + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + // KI ... + + // + ENUM_DRAW_TYPE kiDrawType = showKI ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kiBuffer, true); + SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + // PlotIndexSetInteger(kiBufferPlotIndex, PLOT_DRAW_TYPE, kiDrawType); + + // + PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiColorBuffer, true); + SetIndexBuffer(kiColorBufferIndex, kiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // TKI ... + + // + ENUM_DRAW_TYPE tkiDrawType = showTKI ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tkiBuffer, true); + SetIndexBuffer(tkiBufferIndex, tkiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(tkiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + // PlotIndexSetInteger(tkiBufferPlotIndex, PLOT_DRAW_TYPE, kiDrawType); + + // + PlotIndexSetDouble(tkiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(tkiColorBuffer, true); + SetIndexBuffer(tkiColorBufferIndex, tkiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // VIDYA ... + + // + ENUM_DRAW_TYPE vidyaDrawType = showVidya ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(vidyaBuffer, true); + SetIndexBuffer(vidyaBufferIndex, vidyaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(vidyaBufferPlotIndex, PLOT_SHOW_DATA, showKI); + // PlotIndexSetInteger(vidyaBufferPlotIndex, PLOT_DRAW_TYPE, vidyaDrawType); + + // + PlotIndexSetDouble(vidyaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(vidyaColorBuffer, true); + SetIndexBuffer(vidyaColorBufferIndex, vidyaColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SWINGS ... + + // + ENUM_DRAW_TYPE swingDrawType = showSwings ? DRAW_ARROW : DRAW_NONE; + + // + // SWING Low ... + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferPlotIndex, PLOT_SHOW_DATA, showSwings); + PlotIndexSetInteger(swingLowBufferPlotIndex, PLOT_DRAW_TYPE, swingDrawType); + + // + PlotIndexSetDouble(swingLowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(swingLowBufferPlotIndex, PLOT_ARROW, swingLowArrowCode); + + // + // SWING High ... + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferPlotIndex, PLOT_SHOW_DATA, showSwings); + PlotIndexSetInteger(swingHighBufferPlotIndex, PLOT_DRAW_TYPE, swingDrawType); + + // + PlotIndexSetDouble(swingHighBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(swingHighBufferPlotIndex, PLOT_ARROW, swingHighArrowCode); + + // + // MANALYSER ... + + // + // MAH ... + + // + ENUM_DRAW_TYPE mahDrawType = showMAH ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(mahBuffer, true); + SetIndexBuffer(mahBufferIndex, mahBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mahBufferPlotIndex, PLOT_SHOW_DATA, showMAH); + PlotIndexSetInteger(mahBufferPlotIndex, PLOT_DRAW_TYPE, mahDrawType); + + // + PlotIndexSetDouble(mahBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MAL ... + + // + ENUM_DRAW_TYPE malDrawType = showMAL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(malBuffer, true); + SetIndexBuffer(malBufferIndex, malBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(malBufferPlotIndex, PLOT_SHOW_DATA, showMAL); + PlotIndexSetInteger(malBufferPlotIndex, PLOT_DRAW_TYPE, malDrawType); + + // + PlotIndexSetDouble(malBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MAC ... + + // + ENUM_DRAW_TYPE macDrawType = showMAC ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(macBuffer, true); + SetIndexBuffer(macBufferIndex, macBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(macBufferPlotIndex, PLOT_SHOW_DATA, showMAC); + PlotIndexSetInteger(macBufferPlotIndex, PLOT_DRAW_TYPE, mahDrawType); + + // + PlotIndexSetDouble(macBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(kiStateBuffer, true); + SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(tkiStateBuffer, true); + SetIndexBuffer(tkiStateBufferIndex, tkiStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(vidyaStateBuffer, true); + SetIndexBuffer(vidyaStateBufferIndex, vidyaStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(supBuffer, true); + SetIndexBuffer(supBufferIndex, supBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(resBuffer, true); + SetIndexBuffer(resBufferIndex, resBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Support nad Resistance ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitMarketCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // SHORT ... + sHHBuffer[barIndex] = emptyValue; + sLLBuffer[barIndex] = emptyValue; + + // + // MEDIUM ... + mHHBuffer[barIndex] = emptyValue; + mLLBuffer[barIndex] = emptyValue; + + // + // LONG ... + lHHBuffer[barIndex] = emptyValue; + lLLBuffer[barIndex] = emptyValue; + + // + // HIND ... + hHHBuffer[barIndex] = emptyValue; + hLLBuffer[barIndex] = emptyValue; + + // + // SUPPORT / RESISTANCE ... + supBuffer[barIndex] = emptyValue; + resBuffer[barIndex] = emptyValue; + supportBuffer[barIndex] = emptyValue; + resistanceBuffer[barIndex] = emptyValue; + + // + // PEAKS ... + peakBuffer[barIndex] = emptyValue; + peakGoldenBuffer[barIndex] = emptyValue; + + // + // VALES ... + valeBuffer[barIndex] = emptyValue; + valeGoldenBuffer[barIndex] = emptyValue; + + // + // FiBo ... + fiboLevel1Buffer[barIndex] = emptyValue; + fiboLevel2Buffer[barIndex] = emptyValue; + fiboLevel3Buffer[barIndex] = emptyValue; + fiboLevel4Buffer[barIndex] = emptyValue; + fiboLevel5Buffer[barIndex] = emptyValue; + + // + // SAR ... + sarBuffer[barIndex] = emptyValue; + + // + // TREND ... + trendBuffer[barIndex] = emptyValue; + trendColorBuffer[barIndex] = hideColorIDX; + trendStateBuffer[barIndex] = neuturalState; + + // + // KI ... + kiBuffer[barIndex] = emptyValue; + kiColorBuffer[barIndex] = hideColorIDX; + kiStateBuffer[barIndex] = neuturalState; + + // + // TKI ... + tkiBuffer[barIndex] = emptyValue; + tkiColorBuffer[barIndex] = hideColorIDX; + tkiStateBuffer[barIndex] = neuturalState; + + // + // VIDYA ... + vidyaBuffer[barIndex] = emptyValue; + vidyaColorBuffer[barIndex] = hideColorIDX; + vidyaStateBuffer[barIndex] = neuturalState; + + // + // SWINGS ... + swingLowBuffer[barIndex] = emptyValue; + swingHighBuffer[barIndex] = emptyValue; +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + llMode + // + ); + llBuffer[barIndex] = llValue; +} + +/** + * Claculate Cycles ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculateCycles(int barIndex) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + + // + double iSHH = sHHBuffer[bar_index]; + double iSLL = sLLBuffer[bar_index]; + + // + double iMHH = mHHBuffer[bar_index]; + double iMLL = mLLBuffer[bar_index]; + + // + double iLHH = lHHBuffer[bar_index]; + double iLLL = lLLBuffer[bar_index]; + + // + double iHHH = hHHBuffer[bar_index]; + double iHLL = hLLBuffer[bar_index]; + + // + // Calculate Support ... + double lastSupport = + isFirstBar + ? emptyValue + : supBuffer[lastBarIndex]; + bool isSupport = iSLL == iMLL; + double iSupport = + isSupport + ? iSLL + : lastSupport; + supBuffer[bar_index] = iSupport; + + // + // Calculate Vale ... + double lastVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + bool isVale = + isSupport && + iMLL == iLLL && + iLLL == iHLL; + double iVale = + isVale + ? iMLL + : lastVale; + valeBuffer[bar_index] = iVale; + + // + // Calculate Resistance ... + double lastResistance = + isFirstBar + ? emptyValue + : resBuffer[lastBarIndex]; + bool isResistance = iSHH == iMHH; + double iResistance = + isResistance + ? iSHH + : lastResistance; + resBuffer[bar_index] = iResistance; + + // + // Calculate Peak ... + double lastPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + bool isPeak = + isResistance && + iMHH == iLHH && + iLHH == iHHH; + double iPeak = + isPeak + ? iMHH + : lastPeak; + peakBuffer[bar_index] = iPeak; + + // + bool canSmooth = + supResSmoothingLength > 0 && + supResSmoothingMode != X_MA_MODE_NONE; + if (!canSmooth) + { + // + supportBuffer[bar_index] = iSupport; + resistanceBuffer[bar_index] = iResistance; + } + else + { + // + // Support ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + supResSmoothingLength, + supBuffer, + supportBuffer, + supResSmoothingMode // + ); + + // + // Resistance ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + supResSmoothingLength, + resBuffer, + resistanceBuffer, + supResSmoothingMode // + ); + } + + // + // Calculate Swings ... + + // + double lastSwingLow = + isFirstBar + ? emptyValue + : swingLowBuffer[lastBarIndex]; + double lastSwingHigh = + isFirstBar + ? emptyValue + : swingHighBuffer[lastBarIndex]; + + // + bool isSwingLow = IsSwingLow( + high, + low, + bar_index, + swingLength // + ); + bool isSwingHigh = IsSwingHigh( + high, + low, + bar_index, + swingLength // + ); + bool hasSwing = isSwingLow || + isSwingHigh; + double iSwingLow = emptyValue; + double iSwingHigh = emptyValue; + if (!hasSwing) + { + // + // FillBuffersZero(bar_index); + + // + iSwingLow = lastSwingLow; + iSwingHigh = lastSwingHigh; + + // + swingLowBuffer[bar_index] = lastSwingLow; + swingHighBuffer[bar_index] = lastSwingHigh; + } + else + { + // + iSwingLow = low[bar_index]; + double iSwingHigh = high[bar_index]; + + // + if (isSwingLow && !isSwingHigh) + { + iSwingHigh = lastSwingHigh; + } + else if (isSwingHigh && !isSwingLow) + { + iSwingLow = lastSwingLow; + } + + // + if (iSwingLow > lastSwingLow && + iSwingHigh == lastSwingHigh) + { + iSwingLow = lastSwingLow; + } + + // + if (iSwingHigh < lastSwingHigh && + iSwingLow == lastSwingLow) + { + iSwingHigh = lastSwingHigh; + } + + // + swingLowBuffer[bar_index] = iSwingLow; + swingHighBuffer[bar_index] = iSwingHigh; + } + + // + // Calculate Fibo Levels ... + + // + double iFiboValues[] = { + peakBuffer[bar_index], + valeBuffer[bar_index], + supBuffer[bar_index], + swingLowBuffer[bar_index], + swingHighBuffer[bar_index], + resBuffer[bar_index], // + }; + + // + double iFiboUpper = GetMax(iFiboValues); + double iFiboLower = GetMin(iFiboValues); + + // + // Fibo Level 1 ... + double iFiboLevel1 = emptyValue; + iFiboLevel1 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel1, + X_DIRECTION_BEARISH // + ); + fiboLevel1Buffer[bar_index] = iFiboLevel1; + + // + // Fibo Level 2 ... + double iFiboLevel2 = emptyValue; + iFiboLevel2 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel2, + X_DIRECTION_BEARISH // + ); + fiboLevel2Buffer[bar_index] = iFiboLevel2; + + // + // Fibo Level 3 ... + double iFiboLevel3 = emptyValue; + iFiboLevel3 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel3, + X_DIRECTION_BEARISH // + ); + fiboLevel3Buffer[bar_index] = iFiboLevel3; + + // + // Fibo Level 4 ... + double iFiboLevel4 = emptyValue; + iFiboLevel4 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel4, + X_DIRECTION_BEARISH // + ); + fiboLevel4Buffer[bar_index] = iFiboLevel4; + + // + // Fibo Level 5 ... + double iFiboLevel5 = emptyValue; + iFiboLevel5 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel5, + X_DIRECTION_BEARISH // + ); + fiboLevel5Buffer[bar_index] = iFiboLevel5; + + // + // Calculate Trend Color Buffer ... + double iClose = close[bar_index]; + double iTrend = trendBuffer[bar_index]; + + // + double iTrendState = neuturalState; + double iTrendColor = neuturalColorIDX; + if (iClose > iTrend) + { + // + iTrendState = bullishState; + iTrendColor = !showTrend + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTrend) + { + // + iTrendState = bearishState; + iTrendColor = !showTrend + ? hideColorIDX + : bearishColorIDX; + } + trendStateBuffer[bar_index] = iTrendState; + trendColorBuffer[bar_index] = iTrendColor; + + // + // Calculate KI / Color ... + double lastKI = + isFirstBar + ? emptyValue + : kiBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiBuffer[bar_index] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKI + ? hideColorIDX + : bearishColorIDX; + } + kiStateBuffer[bar_index] = iKIState; + kiColorBuffer[bar_index] = iKIColor; + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + peakGoldenBuffer[bar_index] = iPeakGold; + valeGoldenBuffer[bar_index] = iValeGold; + + // + // TKI State and Color ... + + // + double iTKI = tkiBuffer[bar_index]; + + // + double iTKIState = neuturalState; + double iTKIColor = neuturalColorIDX; + if (iClose > iTKI) + { + // + iTKIState = bullishState; + iTKIColor = + !showTKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTKI) + { + // + iTKIState = bearishState; + iTKIColor = + !showTKI + ? hideColorIDX + : bearishColorIDX; + } + tkiStateBuffer[bar_index] = iTKIState; + tkiColorBuffer[bar_index] = iTKIColor; + + // + // VIDYA Color ... + + // + double iVIDYA = vidyaBuffer[bar_index]; + + // + double iVIDYAState = neuturalState; + double iVIDYAColor = neuturalColorIDX; + if (iClose > iVIDYA) + { + // + iVIDYAState = bullishState; + iVIDYAColor = + !showVidya + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iVIDYA) + { + // + iVIDYAState = bearishState; + iVIDYAColor = + !showVidya + ? hideColorIDX + : bearishColorIDX; + } + vidyaStateBuffer[bar_index] = iVIDYAState; + vidyaColorBuffer[bar_index] = iVIDYAColor; + + // + // Cleanup Resources ... + + // + iBar.Clean(); +} + +// +bool IsSwingLow( + const double &high[], + const double &low[], + int index, + int length // +) +{ + // + bool result = false; + + // + result = index + 1 + length <= firstBarIndex; + if (!result) + { + return result; + } + + // + for (int i = index + 1; i <= index + length; i++) + { + // + result = low[index] < low[i]; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsSwingHigh( + const double &high[], + const double &low[], + int index, + int length // +) +{ + // + bool result = false; + + // + result = index + 1 + length <= firstBarIndex; + if (!result) + { + return result; + } + + // + for (int i = index + 1; i <= index + length; i++) + { + // + result = high[index] > high[i]; + if (!result) + { + break; + } + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xcatb.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xcatb.mq5 new file mode 100644 index 0000000..8fb1e13 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xcatb.mq5 @@ -0,0 +1,2777 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCATB +// Description: Integrates All Requirements inside +// this indicator for analyse Markets to +// Detect Trigger Blocks ... +// +// - HK Bars; +// - ATR Band; +// - Signal Bars; +// - Parabolic Sar; +// - HK Signal Bars; +// - Peaks and Vales; +// - Peaks and Vales Goldens; +// - Trending Average Prices; +// +// - ATR; +// - RSI; +// - ADX; +// - DELTA; +// - VOLUME; +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCATB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCATB" + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x121.xcatb.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// Select Trending Cycle ... +// this Cycle Used for All Calculations ... +input ENUM_X_MARKET_CYCLES appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + +// +// Signal ... +input group "Signal"; +input int signalR2R = 4; // Risk Reward Ratio +input bool drawSignals = true; // Draw Signal +input bool drawTriggerBlock = true; // Draw Trigger Block +input double slAtrMultiplier = 1.0; // ATR Multiplier for SL + +// +// Validating ... +input group "Validating"; +input bool forceHasSwing = false; // Force Blocks to Have Swing +input bool forceObBarType = false; // Force Block Has Reversal Bar +input bool forceOBFVGBarType = false; // Force FVG Has Same Bars +input bool forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity +input bool forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity +input bool validateGapSequence = false; // Validate Block's Gap Sequence +input bool validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + +// +// Filtering ... +input group "Filtering"; +input bool filterBasedOnPV = false; // Filter Based on Peak and Vale +input bool filterBasedOnSar = false; // Filter Based on Sar +input bool filterBasedOnRSI = false; // Filter Based on RSI +input bool filterBasedOnADX = false; // Filter Based on ADX +input bool filterBasedOnATR = false; // Filter Based on ATR +input bool filterBasedOnTrend = false; // Filter Based on Trend +input bool filterBasedOnDelta = false; // Filter Based on Delta +input bool filterBasedOnVolume = false; // Filter Based on Volume +input bool filterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + +// +// Alert ... +input group "Alerts"; +input string mAlertPrefix = ""; // Alert Prefix +input bool _logAlerts = false; // Log Alerts +input bool _pushAlerts = false; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = false; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showPV = false; // Show PV +input bool showPVGolden = false; // Show PV Golden +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showATRBand = false; // Show ATR Band +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +// Non Inputs ... +double sarStep = 0.02; // Step +double sarMax = 0.2; // Maximum +double rsiOBLevel = 70.0; // RSI OB Level +double rsiOSLevel = 30.0; // RSI OS Level +double adxThreshold = 25.0; // ADX Threshold +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +double atrMultiplier = 1.5; // ATR Band Multiplier +bool showShortCycle = false; // Show Short Cycle Range +bool showMediumCycle = false; // Show Medium Cycle Range +bool showLongCycle = false; // Show Long Cycle Range +bool showHindCycle = false; // Show Hind Cycle Range +ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method +ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +ENUM_APPLIED_PRICE trendAppliedTo = PRICE_MEDIAN; // Trend Applied To +ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_EMA; // ATR Signalling Method +ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method +ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +// Plot: 18 +// Color: 4 +// Bar: 8 +// Data Buffer: 19 +#property indicator_buffers 49 +#property indicator_plots 18 + +// +// Plot Buffers ... + +// +// SAR ... + +// +#define sarBufferIndex 0 +#define sarBufferPlotIndex 0 +double sarBuffer[]; + +// +#define sarColorBufferIndex 1 +double sarColorBuffer[]; + +// +#property indicator_label1 "SAR" +#property indicator_type1 DRAW_COLOR_ARROW +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width1 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 2 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +// VALES ... + +// +#define valeBufferIndex 3 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 4 +#define peakGoldenBufferPlotIndex 3 +double peakGoldenBuffer[]; + +// +#property indicator_label4 "PEAK Golden" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 5 +#define valeGoldenBufferPlotIndex 4 +double valeGoldenBuffer[]; + +// +#property indicator_label5 "VALES Golden" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAqua +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 6 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +// +#property indicator_label6 "XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 7 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +// +#property indicator_label7 "XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// TREND ... + +// +#define trendBufferIndex 8 +#define trendBufferPlotIndex 7 +double trendBuffer[]; + +// +#define trendColorBufferIndex 9 +double trendColorBuffer[]; + +// +#property indicator_label8 "Trend" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style8 STYLE_SOLID +#property indicator_width8 2 + +// +// Signal Bar ... + +// +#define sBarOpenBufferIndex 10 +double sBarOpenBuffer[]; + +// +#define sBarHighBufferIndex 11 +double sBarHighBuffer[]; + +// +#define sBarLowBufferIndex 12 +double sBarLowBuffer[]; + +// +#define sBarCloseBufferIndex 13 +double sBarCloseBuffer[]; + +// +#define sBarColorBufferIndex 14 +double sBarColorBuffer[]; + +// +#define sBarBufferPlotIndex 8 +#property indicator_label9 "XSGB Open;XSGB High;XSGB Low;XSGB Close" +#property indicator_type9 DRAW_COLOR_CANDLES +#property indicator_color9 CLR_NONE, clrLime, clrRed + +// +// XHK SIGNAL ... + +// +#define hkSBarOpenBufferIndex 15 +double hkSBarOpenBuffer[]; + +// +#define hkSBarHighBufferIndex 16 +double hkSBarHighBuffer[]; + +// +#define hkSBarLowBufferIndex 17 +double hkSBarLowBuffer[]; + +// +#define hkSBarCloseBufferIndex 18 +double hkSBarCloseBuffer[]; + +// +#define hkSBarColorBufferIndex 19 +double hkSBarColorBuffer[]; + +// +#define hkSBarBufferPlotIndex 9 +#property indicator_label10 "XHKSGB Open;XHKSGB High;XHKSGB Low;XHKSGB Close" +#property indicator_type10 DRAW_COLOR_CANDLES +#property indicator_color10 CLR_NONE, clrAqua, clrMagenta + +// +// CYCLES Range ... + +// +// SHORT ... + +// +#define sHHBufferIndex 20 +#define sHHBufferPlotIndex 10 +double sHHBuffer[]; + +// +#property indicator_label11 "SH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define sLLBufferIndex 21 +#define sLLBufferPlotIndex 11 +double sLLBuffer[]; + +// +#property indicator_label12 "SL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 22 +#define mHHBufferPlotIndex 12 +double mHHBuffer[]; + +// +#property indicator_label13 "MH" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrIndigo +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define mLLBufferIndex 23 +#define mLLBufferPlotIndex 13 +double mLLBuffer[]; + +// +#property indicator_label14 "ML" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrIndigo +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// LONG ... + +// +#define lHHBufferIndex 24 +#define lHHBufferPlotIndex 14 +double lHHBuffer[]; + +// +#property indicator_label15 "LH" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGoldenrod +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define lLLBufferIndex 25 +#define lLLBufferPlotIndex 15 +double lLLBuffer[]; + +// +#property indicator_label16 "LL" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGoldenrod +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// HIND ... + +// +#define hHHBufferIndex 26 +#define hHHBufferPlotIndex 16 +double hHHBuffer[]; + +// +#property indicator_label17 "HH" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrBrown +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +#define hLLBufferIndex 27 +#define hLLBufferPlotIndex 17 +double hLLBuffer[]; + +// +#property indicator_label18 "HL" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrBrown +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 27 + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 1 +double sarStateBuffer[]; + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 2 +double trendStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... + +// +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +// +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +// +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// HK ... + +// +#define openHKBufferIndex mLastBufferIndex + 16 +double openHKBuffer[]; + +// +#define highHKBufferIndex mLastBufferIndex + 17 +double highHKBuffer[]; + +// +#define lowHKBufferIndex mLastBufferIndex + 18 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex mLastBufferIndex + 19 +double closeHKBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Applied Cycle ... +int mAppliedLength; +ENUM_TIMEFRAMES mAppliedPeriod = NULL; + +// +// Handlers ... +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +XCAlert *mAlert; +CArrayObj mObjects; +XCPOIDrawer *mDrawer; +bool mEnableAlerts = false; +XCBarAnalyser *mBarAnalyser; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + ReadBarStyle(); + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; + + // +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + ShowBars(); + + // + mObjects.Clear(); + + // + delete mAlert; + ZeroMemory(mAlert); + + // + delete mDrawer; + ZeroMemory(mDrawer); + + // + delete mBarAnalyser; + ZeroMemory(mBarAnalyser); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + adxThreshold > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + // + IsValid(appliedCycle) && + // + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPVGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // ATR Band ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(sBarColorBuffer, true); + SetIndexBuffer(sBarColorBufferIndex, sBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(sBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(sBarOpenBuffer, true); + SetIndexBuffer(sBarOpenBufferIndex, sBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(sBarHighBuffer, true); + SetIndexBuffer(sBarHighBufferIndex, sBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(sBarLowBuffer, true); + SetIndexBuffer(sBarLowBufferIndex, sBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(sBarCloseBuffer, true); + SetIndexBuffer(sBarCloseBufferIndex, sBarCloseBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL Bar ... + + // + // HK Bars Color ... + ArraySetAsSeries(hkSBarColorBuffer, true); + SetIndexBuffer(hkSBarColorBufferIndex, hkSBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkSBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkSBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkSBarOpenBuffer, true); + SetIndexBuffer(hkSBarOpenBufferIndex, hkSBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkSBarHighBuffer, true); + SetIndexBuffer(hkSBarHighBufferIndex, hkSBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkSBarLowBuffer, true); + SetIndexBuffer(hkSBarLowBufferIndex, hkSBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkSBarCloseBuffer, true); + SetIndexBuffer(hkSBarCloseBufferIndex, hkSBarCloseBuffer, INDICATOR_DATA); + + // + // CYCLES ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); + + // + // XHK ... + + // + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + // Selecte Applied Cycle ... + if (result) + { + // + switch (appliedCycle) + { + // + case X_MARKET_CYCLE_SHORT: + // + mAppliedLength = mSCLength; + mAppliedPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + // + mAppliedLength = mMCLength; + mAppliedPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + // + mAppliedLength = mLCLength; + mAppliedPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + // + mAppliedLength = mHCLength; + mAppliedPeriod = mHCPeriod; + break; + } + } + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + mAppliedLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + mAppliedLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + mAppliedLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mAppliedLength, + 0, + trendMode, + trendAppliedTo // + ); + result = trendHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Initial Class Instances ... + + // + mDrawer = new XCPOIDrawer(); + mBarAnalyser = new XCBarAnalyser(); + + // + // Initialize and Configure Alert ... + mAlert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(mAlertPrefix) + ? "" + : "[" + mAlertPrefix + "]"); + mAlert.SetPrefix(mPrefix); + mAlert.SetLogAlerts(_logAlerts); + mAlert.SetMailAlerts(_mailAlerts); + mAlert.SetPushAlerts(_pushAlerts); + mAlert.SetEnableAlerts(mEnableAlerts); + mAlert.SetTerminalAlerts(_terminalAlerts); + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + sarColorBuffer[barIndex] = hideColorIDX; + trendColorBuffer[barIndex] = hideColorIDX; + + // + atrUpperRawBuffer[barIndex] = emptyValue; + atrLowerRawBuffer[barIndex] = emptyValue; +} + +// +// Custom Handlers ... + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Cycle Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SAR ... + CalculateSAR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SBAR ... + CalculateSBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // HKBAR ... + CalculateHKBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // DELTA ... + CalculateDelta( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // TREND ... + CalculateTrend( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // VOLUME ... + CalculateVolume( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // ATR Band ... + CalculateATRBand( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Try To Detect Trigger Block ... + + // + // Prevent Calculation ... + if (maxBarIndex - barIndex < maxLength) + { + return; + } + + // + XTriggerBlock tb; + bool has = DetectTriggerBlock( + // + _Symbol, + _Period, + // + tb, + // + mBarAnalyser, + // + // Required Buffers ... + atrBuffer, + rsiBuffer, + adxBuffer, + adxpBuffer, + adxnBuffer, + peakBuffer, + valeBuffer, + deltaBuffer, + sarBuffer, + sarStateBuffer, + trendBuffer, + trendStateBuffer, + atrUpperBuffer, + atrLowerBuffer, + sBarOpenBuffer, + sBarCloseBuffer, + hkSBarOpenBuffer, + hkSBarCloseBuffer, + peakGoldenBuffer, + valeGoldenBuffer, + deltaSignalBuffer, + bullishVolumeSignalBuffer, + bearishVolumeSignalBuffer, + // + barIndex, + // + // Signalling ... + signalR2R, + slAtrMultiplier, + // + // Configs ... + rsiOBLevel, + rsiOSLevel, + adxThreshold, + // + // Validators ... + forceObBarType, + forceOBFVGBarType, + forceHasSwing, + forceHasFLiquidity, + forceHasRLiquidity, + validateGapSequence, + validateBlockEdgeBreakout, + // + // Filters ... + filterBasedOnPV, + filterBasedOnSar, + filterBasedOnRSI, + filterBasedOnADX, + filterBasedOnATR, + filterBasedOnTrend, + filterBasedOnDelta, + filterBasedOnVolume, + filterBasedOnSignalBar, + filterBasedOnHKSignalBar // + ); + if (has) + { + // + // Draw ... + if (drawTriggerBlock) + { + // + has = DrawTriggerBlock( + tb, + mDrawer, + mObjects, + NULL, + drawSignals // + ); + } + + // + // Alert ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (has && + (canAlert || + canLogOnly)) + { + // + string message = + tb.trigger.symbol + "," + + ToString(tb.trigger.period) + "> " + + ToString(tb.trigger.dir) + + " Zone Detected at: " + ToString(tb.trigger.to); + + // + if (canLogOnly) + { + mAlert.LogAlert(message); + } + else if (canAlert) + { + mAlert.SendAlert(message); + } + } + } +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +// +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; + + // + // GOLDEN ... + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + + // + peakGoldenBuffer[barIndex] = iPeakGold; + valeGoldenBuffer[barIndex] = iValeGold; + + // + iBar.Clean(); +} + +// +void CalculateSAR( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = low[barIndex]; + double iSar = sarBuffer[barIndex]; + + // + bool isBullish = iSar < iLow; + bool isBearish = iSar > iHigh; + + // + double iSarState = isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iSarColor = iSarState > 0 + ? bullishColorIDX + : iSarState < 0 + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = iSarState; + sarColorBuffer[barIndex] = showSar + ? iSarColor + : hideColorIDX; +} + +// +void CalculateSBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + open, + sBarOpenBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + close, + sBarCloseBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + double max = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + + // + sBarLowBuffer[barIndex] = min; + sBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + sBarOpenBuffer[barIndex] < sBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + sBarColorBuffer[barIndex] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; +} + +// +void CalculateHKBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[barIndex] + high[barIndex] + close[barIndex] + low[barIndex]) / 4; + double iHKHighValue = MathMax(high[barIndex], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[barIndex], MathMin(iHKOpenValue, iHKCloseValue)); + + // + // Raw HK Buffers ... + openHKBuffer[barIndex] = iHKOpenValue; + highHKBuffer[barIndex] = iHKHighValue; + lowHKBuffer[barIndex] = iHKLowValue; + closeHKBuffer[barIndex] = iHKCloseValue; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + openHKBuffer, + hkSBarOpenBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + closeHKBuffer, + hkSBarCloseBuffer, + hkSignalBarMethod // + ); + + // + double min = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + double max = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + + // + hkSBarLowBuffer[barIndex] = min; + hkSBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + hkSBarColorBuffer[barIndex] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; +} + +// +void CalculateDelta( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[barIndex] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); +} + +// +void CalculateTrend( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iClose = close[barIndex]; + double iTrend = trendBuffer[barIndex]; + + // + bool isBullish = iTrend < iLow; + bool isBearish = iTrend > iHigh; + + // + double iTrendState = + isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iTrendColor = + iTrendState > 0 + ? bullishColorIDX + : iTrendState < 0 + ? bearishColorIDX + : neuturalColorIDX; + trendStateBuffer[barIndex] = iTrendState; + trendColorBuffer[barIndex] = showTrend + ? iTrendColor + : hideColorIDX; +} + +// +void CalculateVolume( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[barIndex] = iBullishVolume; + bearishVolumeBuffer[barIndex] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); +} + +// +void CalculateATRBand( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iATR = atrBuffer[barIndex]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[barIndex] = iATRUpper; + atrLowerRawBuffer[barIndex] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[barIndex] = iATRUpper; + atrLowerBuffer[barIndex] = iATRLower; + } +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xcc.mq5 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: X121 XCC +// Description: Candle Styles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121 XCC" + +// +// Holds an SnapShot of Charts Configuration ... +struct XChartStyle +{ + // + // chart's ID ... + long chartId; + // + // chart's mode ... + ENUM_CHART_MODE mode; + // + // show bid line ... + bool showBidLine; + // + // show ask line ... + bool showAskLine; + // + // show grids on chart ... + bool showGrid; + // + // show volumes ... + bool showVolumes; + // + // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ... + bool showTradeLevels; + // + // chart autoscroll ... + bool autoScroll; + // + // chart quick navigation state ... + bool quickNavigation; + // + // chart's foreground color ... + color foreGroundColor; + // + // chart's background color ... + color backGroundColor; + // + // Up Color ... + color upColor; + // + // Down Color ... + color downColor; + // + // Bullish color ... + color bullishColor; + // + // Bearish color ... + color bearishColor; + // + // grid color ... + color gridColor; + // + // bid line color ... + color bidLineColor; + // + // ask line color ... + color askLineColor; + // + // line mode and doji candlestick color ... + color lineColor; + // + // Color of stop order levels (Stop Loss and Take Profit) ... + color stopColor; + // + // volumes color ... + color volumesColor; +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Chart Style"; +input ENUM_CHART_MODE mode = CHART_CANDLES; // Mode +input color upColor = clrGreen; // Up Color +input color downColor = clrRed; // Down Color +input color lineColor = clrGreen; // Line mode and Doji candlestick Color +input color bullishColor = clrGreen; // Bullish Color +input color bearishColor = clrRed; // Bearish Color +input color volumesColor = clrGreen; // Volumes Color + +// +input group "Presentation"; +input bool showCandles = true; // Show Candles + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XChartStyle chartStyle; +XChartStyle clearStyle; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Apply Chart Style ... + ApplyCustomChartStyle(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// Apply Custom Chart Style ... +void ApplyCustomChartStyle() +{ + // + // Read Current Chart Config and Store it ... + ReadChartStyle(); + + // + // After Reading Current Chart Style ... + // we have to Save Configs and Change Styles ... + clearStyle = chartStyle; + + // + clearStyle.upColor = CLR_NONE; + clearStyle.downColor = CLR_NONE; + clearStyle.lineColor = CLR_NONE; + clearStyle.bullishColor = CLR_NONE; + clearStyle.bearishColor = CLR_NONE; + + // + // Decide to Show or not Candles based on User Input ... + if (showCandles) + { + SetChartStyle(chartStyle); + } + else + { + SetChartStyle(clearStyle); + } +} + +// +// Read Previous Chart Style ... +void ReadChartStyle() +{ + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + chartStyle.chartId = chartId; + + // + // Retrieve Chart Mode ... + chartStyle.mode = (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); + + // + chartStyle.showBidLine = (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); + chartStyle.showAskLine = (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); + chartStyle.showGrid = (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); + chartStyle.showVolumes = (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); + chartStyle.showTradeLevels = (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); + chartStyle.autoScroll = (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); + chartStyle.quickNavigation = (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); + + // + chartStyle.foreGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); + chartStyle.backGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); + chartStyle.upColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); + chartStyle.downColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); + chartStyle.bullishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); + chartStyle.bearishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); + chartStyle.gridColor = (color)ChartGetInteger(chartId, CHART_COLOR_GRID); + chartStyle.bidLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_BID); + chartStyle.askLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_ASK); + chartStyle.stopColor = (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); + chartStyle.lineColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); + chartStyle.volumesColor = (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); + + // + chartStyle.mode = mode; + chartStyle.upColor = upColor; + chartStyle.downColor = downColor; + chartStyle.lineColor = lineColor; + chartStyle.bearishColor = bearishColor; + chartStyle.bullishColor = bullishColor; + chartStyle.volumesColor = volumesColor; +} + +// +// Set Chart Style ... +void SetChartStyle( + XChartStyle &mChartStyle // Chart Style to Apply +) +{ + // + ApplyChartStyle( + mChartStyle.chartId, + mChartStyle.mode, + mChartStyle.showBidLine, + mChartStyle.showAskLine, + mChartStyle.showGrid, + mChartStyle.showVolumes, + mChartStyle.showTradeLevels, + mChartStyle.autoScroll, + mChartStyle.quickNavigation, + mChartStyle.foreGroundColor, + mChartStyle.backGroundColor, + mChartStyle.upColor, + mChartStyle.downColor, + mChartStyle.bullishColor, + mChartStyle.bearishColor, + mChartStyle.gridColor, + mChartStyle.bidLineColor, + mChartStyle.askLineColor, + mChartStyle.lineColor, + mChartStyle.stopColor, + mChartStyle.volumesColor); +} + +// +// END Functions ... +// diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xche.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xche.mq5 new file mode 100644 index 0000000..d8ed104 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xche.mq5 @@ -0,0 +1,624 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCHE +// Description: XCHE ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCHE Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCHE" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int cheLength = 35; // Length +input int cheLoopback = 26; // Loopback +input double cheMultiplier1 = 3.0; // 1st Multiplier +input double cheMultiplier2 = 3.5; // 2nd Multiplier +input ENUM_APPLIED_PRICE cheUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied to +input ENUM_APPLIED_PRICE cheLowerAppliedTo = PRICE_LOW; // Lower Zone Applied to + +// +input group "Presentation"; + +// +input int cheArrowCode = 159; // CHE Arrow Code + +// +input bool showLE1 = true; // Show 1st Long Exit +input bool showSE1 = true; // Show 1st Short Exit +input bool showLE2 = true; // Show 2st Long Exit +input bool showSE2 = true; // Show 2st Short Exit + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Exit 1 ... + +// +// LONG ... + +// +#define le1BufferIndex 0 +double le1Buffer[]; + +#property indicator_label1 "X121 LE1" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// SHORT ... + +// +#define se1BufferIndex 1 +double se1Buffer[]; + +#property indicator_label2 "X121 SE1" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Exit 2 ... + +// +// LONG ... + +// +#define le2BufferIndex 2 +double le2Buffer[]; + +#property indicator_label3 "X121 LE2" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAqua +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// SHORT ... + +// +#define se2BufferIndex 3 +double se2Buffer[]; + +#property indicator_label4 "X121 SE2" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Start Buffers ... + +// +#define le1StartBufferIndex 4 +double le1StartBuffer[]; + +// +#property indicator_label5 "X121 LE1 S" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrLime + +// +#define se1StartBufferIndex 5 +double se1StartBuffer[]; + +// +#property indicator_label6 "X121 SE1 S" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrRed + +// +#define le2StartBufferIndex 6 +double le2StartBuffer[]; + +// +#property indicator_label7 "X121 LE2 S" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrLime + +// +#define se2StartBufferIndex 7 +double se2StartBuffer[]; + +// +#property indicator_label8 "X121 SE2 S" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrRed + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Working Array ... +double work[][6]; +#define hi1Idx 0 +#define lo1Idx 1 +#define hi2Idx 2 +#define lo2Idx 3 +#define trend1Idx 4 +#define trend2Idx 5 + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input cheLength, here we get max Input cheLength + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + if (Bars(_Symbol, _Period) < rates_total) + { + return (prev_calculated); + } + + // + if (ArrayRange(work, 0) != rates_total) + { + ArrayResize(work, rates_total); + } + + // + // this counts Available Bars ... + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + low, + close); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + cheLength >= 9 && + cheLoopback >= 0; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(cheLength, cheLoopback); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // LEVEL 1 ... + + // + // Long Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE le1DrawType = showLE1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE le1StartDrawType = showLE1 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(le1BufferIndex, le1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(le1BufferIndex, PLOT_SHOW_DATA, showLE1); + PlotIndexSetInteger(le1BufferIndex, PLOT_DRAW_TYPE, le1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(le1StartBufferIndex, le1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_DRAW_TYPE, le1StartDrawType); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // Short Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE se1DrawType = showSE1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE se1StartDrawType = showSE1 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(se1BufferIndex, se1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(se1BufferIndex, PLOT_SHOW_DATA, showSE1); + PlotIndexSetInteger(se1BufferIndex, PLOT_DRAW_TYPE, se1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(se1StartBufferIndex, se1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_DRAW_TYPE, se1StartDrawType); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // LEVEL 2 ... + + // + // Long Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE le2DrawType = showLE2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE le2StartDrawType = showLE2 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(le2BufferIndex, le2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(le2BufferIndex, PLOT_SHOW_DATA, showLE2); + PlotIndexSetInteger(le2BufferIndex, PLOT_DRAW_TYPE, le2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(le2StartBufferIndex, le2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_DRAW_TYPE, le2StartDrawType); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // Short Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE se2DrawType = showSE2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE se2StartDrawType = showSE2 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(se2BufferIndex, se2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(se2BufferIndex, PLOT_SHOW_DATA, showSE2); + PlotIndexSetInteger(se2BufferIndex, PLOT_DRAW_TYPE, se2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(se2StartBufferIndex, se2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_DRAW_TYPE, se2StartDrawType); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_ARROW, cheArrowCode); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Buffers ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + int prevCalculated, // Previous Calculated + int ratesTotal, // Total Rates + const double &open[], // Rates Open ... + const double &high[], // Rates High ... + const double &low[], // Rates Low ... + const double &close[] // Rates Close ... +) +{ + // + // Cleanup Buffers ... + le1Buffer[bar_index] = le1StartBuffer[bar_index] = se1Buffer[bar_index] = se1StartBuffer[bar_index] = EMPTY_VALUE; + le2Buffer[bar_index] = le2StartBuffer[bar_index] = se2Buffer[bar_index] = se2StartBuffer[bar_index] = EMPTY_VALUE; + + // + int start = MathMax(bar_index - cheLoopback, 0); + + // + // Calculate ATR Value ... + double atrValue = 0; + for (int k = 1; k <= cheLength && (bar_index - k - 1) >= 0; k++) + { + // + atrValue += MathMax(high[bar_index - k], close[MathMax(bar_index - k - 1, 0)]) - + MathMin(low[bar_index - k], close[MathMax(bar_index - k - 1, 0)]); + } + atrValue /= (double)cheLength; + + // + // Retrieve Highest High and Lowest Lows ... + double cheLoopbackMax = high[ArrayMaximum(high, start, cheLoopback)]; + double cheLoopbackMin = low[ArrayMinimum(low, start, cheLoopback)]; + + // + // Fill Multi Dimesional Working Array ... + work[bar_index][hi1Idx] = cheLoopbackMax - cheMultiplier1 * atrValue; + work[bar_index][lo1Idx] = cheLoopbackMin + cheMultiplier1 * atrValue; + work[bar_index][hi2Idx] = cheLoopbackMax - cheMultiplier2 * atrValue; + work[bar_index][lo2Idx] = cheLoopbackMin + cheMultiplier2 * atrValue; + work[bar_index][trend1Idx] = (bar_index > 0) ? work[bar_index - 1][trend1Idx] : 0; + work[bar_index][trend2Idx] = (bar_index > 0) ? work[bar_index - 1][trend2Idx] : 0; + + // + if (bar_index > 0) + { + // + // Calculate Trends ... + if (close[bar_index] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][trend1Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][trend1Idx] = -1; + } + + // + if (close[bar_index] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][trend2Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][trend2Idx] = -1; + } + + // + // Calculate Exit Values ... + + // + // Exit 1 ... + + // + // Long ... + if (cheMultiplier1 > 0 && work[bar_index][trend1Idx] == 1) + { + // + if (work[bar_index][hi1Idx] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][hi1Idx] = work[bar_index - 1][hi1Idx]; + } + + // + le1Buffer[bar_index] = work[bar_index][hi1Idx]; + + // + if (le1Buffer[bar_index - 1] == EMPTY_VALUE) + { + le1StartBuffer[bar_index] = le1Buffer[bar_index]; + } + } + + // + // Short ... + if (cheMultiplier1 > 0 && work[bar_index][trend1Idx] == -1) + { + // + if (work[bar_index][lo1Idx] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][lo1Idx] = work[bar_index - 1][lo1Idx]; + } + + // + se1Buffer[bar_index] = work[bar_index][lo1Idx]; + + // + if (se1Buffer[bar_index - 1] == EMPTY_VALUE) + { + se1StartBuffer[bar_index] = se1Buffer[bar_index]; + } + } + + // + // Exit 2 ... + + // + // Long ... + if (cheMultiplier2 > 0 && work[bar_index][trend2Idx] == 1) + { + if (work[bar_index][hi2Idx] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][hi2Idx] = work[bar_index - 1][hi2Idx]; + } + + // + le2Buffer[bar_index] = work[bar_index][hi2Idx]; + + // + if (le2Buffer[bar_index - 1] == EMPTY_VALUE) + { + le2StartBuffer[bar_index] = le2Buffer[bar_index]; + } + } + + // + // Short ... + if (cheMultiplier2 > 0 && work[bar_index][trend2Idx] == -1) + { + // + if (work[bar_index][lo2Idx] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][lo2Idx] = work[bar_index - 1][lo2Idx]; + } + + // + se2Buffer[bar_index] = work[bar_index][lo2Idx]; + + // + if (se2Buffer[bar_index - 1] == EMPTY_VALUE) + { + se2StartBuffer[bar_index] = se2Buffer[bar_index]; + } + } + } +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..286882a --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121 XCT +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCT Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121 XCT" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input int fontSize = 15; // Font Size +input string font = "Arial"; // Font +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showTimer = true; // Show Candle Time + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +bool isCreatedObject; +string tag; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + + // + tag = ShortName + _Symbol + ToString(_Period); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Delete Object ... + ObjectDelete(0, tag); + + // + Comment(""); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + if (!showTimer) + { + return rates_total; + } + + // + XBarRemainsTime barRemains; + barRemains.Init( + _Symbol, + _Period + // + ); + + // + string msg = barRemains + .ToString( + "", + "", + "", + "", + "", + ":", + true + // + ); + + // + long mSpread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); + + // + string _sp = ""; + if (mSpread < 10) + _sp = ".."; + else if (mSpread < 100) + _sp = "."; + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + ", Next Bar in: " + msg; + + // + if (IsValid(tag) && !isCreatedObject) + { + CreateIndicatorObject(); + } + + // + if (isCreatedObject) + { + ObjectSetString(0, tag, OBJPROP_TEXT, objText); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +void CreateIndicatorObject() +{ + // + if (!showTimer || + !IsValid(tag)) + { + return; + } + + // + isCreatedObject = ObjectCreate(0, tag, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, tag, OBJPROP_CORNER, corner); + ObjectSetInteger(0, tag, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, tag, OBJPROP_YDISTANCE, 2); + + // + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + int mFontSize = fontSize > 0 + ? fontSize + : 10; + + // + string mFont = IsValid(font) + ? font + : "Arial"; + + // + ObjectSetString(0, tag, OBJPROP_FONT, mFont); + ObjectSetInteger(0, tag, OBJPROP_COLOR, clr); + ObjectSetInteger(0, tag, OBJPROP_ANCHOR, Anchor); + ObjectSetInteger(0, tag, OBJPROP_FONTSIZE, mFontSize); +} + +// +// END Functions ... +// diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xczone.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xczone.mq5 new file mode 100644 index 0000000..f6d56a4 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xczone.mq5 @@ -0,0 +1,2452 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 X3MA +// Description: X3MA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCZone Indicator" +#property strict + +// +// Definitions ... +// +#define ShortName "X121 XCZone" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Inputs ... +input group "Market"; +input ENUM_X_PERIOD_METHOD trendPeriodMethod = X_PERIOD_AUTO; // How to Find Trend Period +input ENUM_TIMEFRAMES trendPeriod = NULL; // Trend Time Period +input ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +input ENUM_APPLIED_PRICE trendAppliedTo = PRICE_CLOSE; // Trend Applied To +input double sarStep = 0.02; // Sar Step +input double sarMax = 0.2; // Sar Maximum +input int adxLength = 14; // ADX Length +input double adxThreshold = 25.0; // ADX Threshold +input int rsiLength = 14; // RSI Length +input double rsiOBLevel = 70.0; // RSI OB Level +input double rsiOSLevel = 30.0; // RSI OS Level +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input int deltaSignalLength = 14; // Delta Signal Length +input ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +input int volumeSignalLength = 14; // Volume Signal Length +input ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +// Validating ... +input group "Validating"; +input int minZoneLength = 7; // Minimum Length of Consolidation Zone +input double maxZoneRangeInPoints = 70; // Max Zone Range in Point +input double maxAllowedEntryDistance = 30; // Max Allowed Entry Distance +input bool forceGapBarsBreakout = true; // Force Zone's Gap Bar's Breakes Out +input bool forceHasSwing = true; // Force Zone's Has Propper Swing +input bool forceHasPinBarEntry = true; // Force Zone's Ends with a Pin Bar + +// +// Filtering ... +input group "Filtering"; +input bool filterBasedOnSar = false; // Filter Pivots Based on Sar +input bool filterBasedOnRSI = false; // Filter Pivots Based on RSI +input bool filterBasedOnADX = false; // Filter Pivots Based on ADX +input bool filterBasedOnTrend = false; // Filter Pivots Based on Trend + +// +// Presentation ... +input group "Presentation"; +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool rayLeft = false; // Ray to Left +input bool drawZones = true; // Draw Detected Zones +input bool drawRRofZones = true; // Draw Zone's Risk Reward Ratios +input int boxWidth = 2; // Box Width +input color bullishColor = clrLime; // Bullish Color +input color bearishColor = clrRed; // Bearish Color +input ENUM_LINE_STYLE boxStyle = STYLE_SOLID; // Box Style + +// +input int startCalculationForLastBars = 5000; // Calculate Last n Bars +int sarArrowCode = 159; // Sar Arrow Code +int rrZoneLength = 7; // Draw Risk Reward Ratio till n Bars + +// +// Alert ... +input group "Alerts"; +input string alertPrefix = ""; // Alert Prefix +input bool _logAlerts = true; // Log Alerts +input bool _pushAlerts = true; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = true; // Terminal Alerts + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 16 +#property indicator_plots 2 + +// +// Plot Buffers ... + +// +// TREND ... + +// +#define trendBufferIndex 0 +#define trendBufferPlotIndex 0 +double trendBuffer[]; + +// +#define trendColorBufferIndex 1 +double trendColorBuffer[]; + +// +#property indicator_label1 "X121 Trend" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_DASH +#property indicator_width1 2 + +// +// SAR ... + +// +#define sarBufferIndex 2 +#define sarBufferPlotIndex 2 +double sarBuffer[]; + +// +#define sarColorBufferIndex 3 +double sarColorBuffer[]; + +// +#property indicator_label2 "X121 SAR" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_width2 2 + +// +// Data Buffers ... + +#define mLastBufferIndex 3 + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 1 +double trendStateBuffer[]; + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 2 +double sarStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +XCAlert *alert; +double mPoints = 0; +CArrayObj mObjects; +XCPOIDrawer *drawer; +bool mEnableAlerts = false; +XCBarAnalyser *barAnalyser; +int mTrendPeriodLength = 0; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; +ENUM_TIMEFRAMES mTrendPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // Configure Alert ... + alert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(alertPrefix) + ? "" + : "[" + alertPrefix + "]"); + alert.SetPrefix(mPrefix); + alert.SetLogAlerts(_logAlerts); + alert.SetMailAlerts(_mailAlerts); + alert.SetPushAlerts(_pushAlerts); + alert.SetEnableAlerts(mEnableAlerts); + alert.SetTerminalAlerts(_terminalAlerts); + + // + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + // Initializing TrendPeriod ... + int cPeriodSeconds = PeriodSeconds(_Period); + if (trendPeriodMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mTrendPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mTrendPeriod = trendPeriod; + } + if (IsValid(mTrendPeriod)) + { + mTrendPeriodLength = PeriodSeconds(mTrendPeriod) / cPeriodSeconds; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = adxHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mTrendPeriodLength, + 0, + trendMode, + trendAppliedTo // + ); + isInited = trendHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + mPoints = GetPoints(_Symbol); + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + mObjects.Clear(); + + // + delete alert; + delete drawer; + + // + ZeroMemory(alert); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + + // + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + adxLength > 0 && + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + sarMax > sarStep && + minZoneLength > 2 && + deltaSignalLength > 2 && + volumeSignalLength > 2 && + deltaSignalMethod != X_MA_MODE_NONE && + volumeSignalMethod != X_MA_MODE_NONE && + IsValid(trendPeriodMethod, trendPeriod) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(minZoneLength, rsiLength); + result = MathMax(result, adxLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + + // + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + + // + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + // Bar Info ... + double iLow = high[bar_index]; + double iHigh = high[bar_index]; + double iClose = close[bar_index]; + double iOpen = open[bar_index]; + double iVolume = (double)iVolume(_Symbol, _Period, bar_index); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double points = GetPoints(_Symbol); + + // + // Calculate Sar Color Buffer ... + double iSar = sarBuffer[bar_index]; + + // + double iSarState = neuturalState; + double iSarColor = neuturalColorIDX; + if (iLow > iSar) + { + // + iSarState = bullishState; + iSarColor = !showSar + ? hideColorIDX + : bullishColorIDX; + } + else if (iHigh < iSar) + { + // + iSarState = bearishState; + iSarColor = !showSar + ? hideColorIDX + : bearishColorIDX; + } + sarStateBuffer[bar_index] = iSarState; + sarColorBuffer[bar_index] = iSarColor; + + // + // Calculate Trend Color Buffer ... + double iTrend = trendBuffer[bar_index]; + + // + double iTrendState = neuturalState; + double iTrendColor = neuturalColorIDX; + if (iClose > iTrend) + { + // + iTrendState = bullishState; + iTrendColor = !showTrend + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTrend) + { + // + iTrendState = bearishState; + iTrendColor = !showTrend + ? hideColorIDX + : bearishColorIDX; + } + trendStateBuffer[bar_index] = iTrendState; + trendColorBuffer[bar_index] = iTrendColor; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[bar_index] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + deltaSignalLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); + + // + // VOLUME ... + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[bar_index] = iBullishVolume; + bearishVolumeBuffer[bar_index] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + // Detect Trigger Zone ... + DetectTriggerZone( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +// +void DetectTriggerZone( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + + // + int lastBarIndex = bar_index + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + bar_index == maxBarIndex; + + // + // Prevent Calculation ... + if (maxBarIndex - bar_index < minZoneLength) + { + return; + } + + // + int zIDX = 0; + int cIDX = 0; + int pIDX = 0; + int p2IDX = 0; + int p3IDX = 0; + int p4IDX = 0; + double ll = 0; + double hh = 0; + bool has = false; + ENUM_X_DIRECTION iDir; + + // + // Retrieve Required Bars ... + + // + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ... + XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ... + XOHCL p2Bar; // Determines FVG's Start Bar in a Block ... + XOHCL p3Bar; // First Verification of Block ... + XOHCL p4Bar; // Seccond Verification of Block ... + + // + has = zBar.Init( + _Symbol, + _Period, + bar_index // + ); + has = + has && + zBar.GetPreviousBar(cBar); + has = + has && + cBar.GetPreviousBar(pBar); + has = + has && + pBar.GetPreviousBar(p2Bar); + has = + has && + p2Bar.GetPreviousBar(p3Bar); + has = + has && + p3Bar.GetPreviousBar(p4Bar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + // Define Zone Structure ... + XBoxZone zone; + + // + // Detect Based Order Block using CBar ... + has = barAnalyser.IsOB( + cBar, + zone, + true, // Force FVG Bar Type ... + true // Force Block Two Bar Checking ... + ); + + // + // Ensure a Block is Detected ... + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + zIDX = zBar.Index(); + cIDX = cBar.Index(); + pIDX = pBar.Index(); + p2IDX = p2Bar.Index(); + p3IDX = p3Bar.Index(); + p4IDX = p4Bar.Index(); + + // + bool isBullish = + has && + zone.IsBullish(); + + // + bool isBearish = + has && + zone.IsBearish(); + + // + int toIDX = zone.ToIndex(); + int fromIDX = zone.FromIndex(); + + // + // Validating p2Bar and p3Bar Direction ... + if (has) + { + // + iDir = Opposit(zone.dir); + + // + has = + iDir == p3Bar.GetDirection() || + iDir == p4Bar.GetDirection(); + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Start Validating Block based on + // Detected One ... + + // + // Validating Using Max Range ... + has = maxZoneRangeInPoints > 0; + if (has) + { + // + double range = zone.GetRange(); + has = range <= maxZoneRangeInPoints * mPoints; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validate Gap Endup with PinBar ... + has = forceHasPinBarEntry; + if (has) + { + // + bool isBullishRejected = + isBullish && + cBar.IsBullish() && + cBar.GetLowShadow() > cBar.GetHighShadow(); + + // + bool isBearishRejected = + isBearish && + cBar.IsBearish() && + cBar.GetLowShadow() < cBar.GetHighShadow(); + + // + has = isBullishRejected || + isBearishRejected; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validating Gap Bar must a Momentum Bar and + // Breakes out Zone's Directional Edge ... + // for Bullish: Upper + // for Bearish: Lower + has = forceGapBarsBreakout; + if (has) + { + // + // Gap Bar is PBar ... + + // + // Check Gap Bar is Momentum Bar ... + has = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + has && + IsBullish(iDir); + bool isBearishMomentum = + has && + IsBearish(iDir); + + // + // Check Gap Bar's Breakout ... + + // + bool isBullishBreakedout = + isBullish && + pBar.IsBullish() && + isBullishMomentum && + pBar.GetUp() > zone.upper && + pBar.GetDown() < zone.upper; + + // + bool isBearishBreakedout = + isBearish && + pBar.IsBearish() && + isBearishMomentum && + pBar.GetUp() > zone.lower && + pBar.GetDown() < zone.lower; + + // + has = isBullishBreakedout || + isBearishBreakedout; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validate Zone Has Propper Swing ... + // for Bullish: p2Bar or p3Bar must be a Swing Low ... + // for Bearish: p2Bar or p3Bar must be a Swing High ... + has = forceHasSwing; + if (has) + { + // + // p2Bar ... + bool isP2BarSwing = + barAnalyser + .IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarSwingLow = + isP2BarSwing && + IsBullish(iDir); + bool isP2BarSwingHigh = + isP2BarSwing && + IsBearish(iDir); + + // + // p3Bar ... + bool isP3BarSwing = + barAnalyser + .IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarSwingLow = + isP3BarSwing && + IsBullish(iDir); + bool isP3BarSwingHigh = + isP3BarSwing && + IsBearish(iDir); + + // + bool hasSwingLow = + isBullish && + (isP2BarSwingLow || + isP3BarSwingLow); + + // + bool hasSwingHigh = + isBearish && + (isP2BarSwingHigh || + isP3BarSwingHigh); + + // + has = + hasSwingLow || + hasSwingHigh; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validating Using Swing Length ... + has = minZoneLength > 0; + if (has) + { + // + XOHCL fromBar; + has = zone.FromBar(fromBar); + if (has) + { + // + // Retrieve HH and LL ... + ll = fromBar.FindLowest(minZoneLength, MODE_LOW); + hh = fromBar.FindHighest(minZoneLength, MODE_HIGH); + + // + // Validate Using HH and LL ... + + // + bool isBullishValid = + isBullish && + ll >= zone.lower; + + // + bool isBearishValid = + isBearish && + hh <= zone.upper; + + // + has = isBullishValid || + isBearishValid; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + // Update Zone's From Time ... + zone.from = GetBarTime( + zone.symbol, + zone.period, + fromBar.Index() + minZoneLength // + ); + } + + // + fromBar.Clean(); + } + + // + // Validate Max Allowed Entry Distance ... + has = maxAllowedEntryDistance > 0; + if (has) + { + // + double base = + isBullish + ? zone.upper + : zone.lower; + double entryDistance = MathAbs(zBar.open - base); + has = entryDistance <= maxAllowedEntryDistance * mPoints; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Here we Ensure which have a Valid Zone using Different Applied Validations ... + // from now we are Going to Filtered Validate Zones ... + + // + // Check Exists Filters or not ... + has = filterBasedOnSar || + filterBasedOnRSI || + filterBasedOnADX || + filterBasedOnTrend; + if (has) + { + // + // Do Apply Several Exists Filters ... + + // + // SAR Filter ... + if (filterBasedOnSar) + { + // + // Reading Conditions Values ... + + // + double zSar = sarBuffer[zIDX]; + double cSar = sarBuffer[cIDX]; + double pSar = sarBuffer[pIDX]; + double p2Sar = sarBuffer[p2IDX]; + double p3Sar = sarBuffer[p3IDX]; + double p4Sar = sarBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isZSarBearish = zSar > zBar.high; + + // + bool isCSarBullish = cSar < cBar.low; + bool isCSarBearish = cSar > cBar.high; + + // + bool isPSarBullish = pSar < pBar.low; + bool isPSarBearish = pSar > pBar.high; + + // + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP2SarBearish = p2Sar > p2Bar.high; + + // + bool isCSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + !isPSarBullish && + cBar.IsBullish() && + cBar.GetUp() > pSar; + + // + bool isCSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + !isPSarBearish && + cBar.IsBearish() && + cBar.GetDown() < pSar; + + // + bool isPSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + isPSarBullish && + !isP2SarBullish && + pBar.IsBullish() && + pBar.GetUp() > p2Sar; + + // + bool isPSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + isPSarBearish && + !isP2SarBearish && + pBar.IsBearish() && + pBar.GetDown() < p2Sar; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + (isCSarSwitchedToBullish || + isPSarSwitchedToBullish); + + // + bool isBearishFiltered = + isBearish && + (isCSarSwitchedToBearish || + isPSarSwitchedToBearish); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // RSI Filter ... + if (filterBasedOnRSI) + { + // + // Reading Conditions Values ... + + // + double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2; + + // + double zRSI = rsiBuffer[zIDX]; + double cRSI = rsiBuffer[cIDX]; + double pRSI = rsiBuffer[pIDX]; + double p2RSI = rsiBuffer[p2IDX]; + double p3RSI = rsiBuffer[p3IDX]; + double p4RSI = rsiBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZRSIBullish = zRSI > rsiTrend; + bool isZRSIBearish = zRSI < rsiTrend; + + // + bool isCRSIBullish = cRSI > rsiTrend; + bool isCRSIBearish = cRSI < rsiTrend; + + // + bool isPRSIBullish = pRSI > rsiTrend; + bool isPRSIBearish = pRSI < rsiTrend; + + // + bool isP2RSIBullish = p2RSI > rsiTrend; + bool isP2RSIBearish = p2RSI < rsiTrend; + + // + bool isP3RSIBullish = p3RSI > rsiTrend; + bool isP3RSIBearish = p3RSI < rsiTrend; + + // + // Trending Conditions ... + + // + bool isCRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + !isPRSIBullish; + + // + bool isCRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + !isPRSIBearish; + + // + bool isPRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + !isP2RSIBullish; + + // + bool isPRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + !isP2RSIBearish; + + // + bool isP2RSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + isP2RSIBullish && + !isP3RSIBullish; + + // + bool isP2RSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + isP2RSIBearish && + !isP3RSIBearish; + + // + // Crosses Conditions ... + + // + bool isCBarCrossedOverOS = + zRSI > rsiOSLevel && + cRSI > rsiOSLevel && + pRSI <= rsiOSLevel; + + // + bool isCBarCrossedUnderOB = + zRSI < rsiOBLevel && + cRSI < rsiOBLevel && + pRSI >= rsiOBLevel; + + // + bool isPBarCrossedOverOS = + zRSI > rsiOSLevel && + cRSI > rsiOSLevel && + pRSI > rsiOSLevel && + p2RSI <= rsiOSLevel; + + // + bool isPBarCrossedUnderOB = + zRSI < rsiOBLevel && + cRSI < rsiOBLevel && + pRSI < rsiOBLevel && + p2RSI >= rsiOBLevel; + + // + // V Pattern Conditions ... + + // + bool isCRSIHasVBullishPattern = + zRSI >= cRSI && + cRSI > pRSI && + p2RSI > pRSI && + cRSI >= p2RSI; + + // + bool isCRSIHasVBearishPattern = + zRSI <= cRSI && + cRSI < pRSI && + p2RSI < pRSI && + cRSI <= p2RSI; + + // + // Continuation Conditions ... + + // + bool isRSIUp = + zRSI >= cRSI && + (cRSI >= pRSI || + pRSI >= p2RSI || + p2RSI >= p3RSI); + + // + bool isRSIDown = + zRSI <= cRSI && + (cRSI <= pRSI || + pRSI <= p2RSI || + p2RSI <= p3RSI); + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isRSIUp + // + || + // + // Crosses ... + (isCBarCrossedOverOS || + isPBarCrossedOverOS) + // + || + // + // V Pattern ... + isCRSIHasVBullishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBullish || + isPRSISwitchedToBullish || + isP2RSISwitchedToBullish) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isRSIDown + // + || + // + // Crosses ... + (isCBarCrossedUnderOB || + isPBarCrossedUnderOB) + // + || + // + // V Pattern ... + isCRSIHasVBearishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBearish || + isPRSISwitchedToBearish || + isP2RSISwitchedToBearish) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // ADX Filter ... + if (filterBasedOnADX) + { + // + // Reading Conditions Values ... + + // + // ADX ... + double zADX = adxBuffer[zIDX]; + double cADX = adxBuffer[cIDX]; + double pADX = adxBuffer[pIDX]; + double p2ADX = adxBuffer[p2IDX]; + double p3ADX = adxBuffer[p3IDX]; + double p4ADX = adxBuffer[p4IDX]; + + // + // ADX +DI ... + double zADXP = adxpBuffer[zIDX]; + double cADXP = adxpBuffer[cIDX]; + double pADXP = adxpBuffer[pIDX]; + double p2ADXP = adxpBuffer[p2IDX]; + double p3ADXP = adxpBuffer[p3IDX]; + double p4ADXP = adxpBuffer[p4IDX]; + + // + // ADX -DI ... + double zADXN = adxnBuffer[zIDX]; + double cADXN = adxnBuffer[cIDX]; + double pADXN = adxnBuffer[pIDX]; + double p2ADXN = adxnBuffer[p2IDX]; + double p3ADXN = adxnBuffer[p3IDX]; + double p4ADXN = adxnBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isADXUp = + zADX >= cADX && + (cADX >= pADX || + pADX >= p2ADX); + + // + bool isADXDown = + zADX <= cADX && + (cADX <= pADX || + pADX <= p2ADX); + + // + // Trending ... + + // + bool isZADXBullish = zADX > adxThreshold; + bool isZADXBearish = zADX < adxThreshold; + + // + bool isCADXBullish = cADX > adxThreshold; + bool isCADXBearish = cADX < adxThreshold; + + // + bool isPADXBullish = pADX > adxThreshold; + bool isPADXBearish = pADX < adxThreshold; + + // + bool isP2ADXBullish = p2ADX > adxThreshold; + bool isP2ADXBearish = p2ADX < adxThreshold; + + // + bool isP3ADXBullish = p3ADX > adxThreshold; + bool isP3ADXBearish = p3ADX < adxThreshold; + + // + bool isP4ADXBullish = p4ADX > adxThreshold; + bool isP4ADXBearish = p4ADX < adxThreshold; + + // + bool isCADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + !isPADXBullish; + + // + bool isCADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + isPADXBearish && + !isP2ADXBearish; + + // + // Powering ... + + // + bool isZADXHasBullishPower = zADXP > zADXN; + bool isZADXHasBearishPower = zADXN > zADXP; + + // + bool isCADXHasBullishPower = cADXP > cADXN; + bool isCADXHasBearishPower = cADXN > cADXP; + + // + bool isPADXHasBullishPower = pADXP > pADXN; + bool isPADXHasBearishPower = pADXN > pADXP; + + // + bool isP2ADXHasBullishPower = p2ADXP > p2ADXN; + bool isP2ADXHasBearishPower = p2ADXN > p2ADXP; + + // + bool isP3ADXHasBullishPower = p3ADXP > p3ADXN; + bool isP3ADXHasBearishPower = p3ADXN > p3ADXP; + + // + bool isP4ADXHasBullishPower = p4ADXP > p4ADXN; + bool isP4ADXHasBearishPower = p4ADXN > p4ADXP; + + // + bool isCADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + !isPADXHasBullishPower; + + // + bool isCADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + !isPADXHasBearishPower; + + // + bool isPADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + isPADXHasBullishPower && + !isP2ADXHasBullishPower; + + // + bool isPADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + isPADXHasBearishPower && + !isP2ADXHasBearishPower; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isADXUp + // + || + // + // Trending ... + (isCADXSwitchedToBullish || + isPADXSwitchedToBullish) + // + || + // + // Powering ... + (isCADXSwitchedToBullishPower || + isPADXSwitchedToBullishPower) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isADXDown + // + || + // + // Trending ... + (isCADXSwitchedToBearish || + isPADXSwitchedToBearish) + // + || + // + // Powering ... + (isCADXSwitchedToBearishPower || + isPADXSwitchedToBearishPower) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // TREND Filter ... + if (filterBasedOnTrend) + { + // + // Reading Conditions Values ... + + // + double zTrend = trendBuffer[zIDX]; + double cTrend = trendBuffer[cIDX]; + double pTrend = trendBuffer[pIDX]; + double p2Trend = trendBuffer[p2IDX]; + double p3Trend = trendBuffer[p3IDX]; + double p4Trend = trendBuffer[p4IDX]; + + // + double trends[] = { + zTrend, + cTrend, + pTrend, + p2Trend, + p3Trend, + p4Trend // + }; + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + double zTrendState = trendStateBuffer[zIDX]; + double cTrendState = trendStateBuffer[cIDX]; + double pTrendState = trendStateBuffer[pIDX]; + double p2TrendState = trendStateBuffer[p2IDX]; + double p3TrendState = trendStateBuffer[p3IDX]; + double p4TrendState = trendStateBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isTrendUp = + zTrend >= cTrend && + cTrend >= trendsAVG && + cTrend > trendsMin; + + // + bool isTrendDown = + zTrend <= cTrend && + cTrend <= trendsAVG && + cTrend < trendsMax; + + // + // Stating ... + + // + bool isCTrendBullish = + zTrendState > 0 && + cTrendState > 0; + + // + bool isCTrendBearish = + zTrendState < 0 && + cTrendState < 0; + + // + bool isPTrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0; + + // + bool isPTrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0; + + // + bool isP2TrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0 && + p2TrendState > 0; + + // + bool isP2TrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0 && + p2TrendState < 0; + + // + bool isCTrendSwitchedToBullish = + isCTrendBullish && + !isPTrendBullish; + + // + bool isCTrendSwitchedToBearish = + isCTrendBearish && + !isPTrendBearish; + + // + bool isPTrendSwitchedToBullish = + isCTrendBullish && + isPTrendBullish && + !isP2TrendBullish; + + // + bool isPTrendSwitchedToBearish = + isCTrendBearish && + isPTrendBearish && + !isP2TrendBearish; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isTrendUp + // + || + // + // Trend Stating ... + (isCTrendBullish && + isPTrendBullish) + // + || + // + // Switching ... + (isCTrendSwitchedToBullish || + isPTrendSwitchedToBullish) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isTrendDown + // + || + // + // Trend Stating ... + (isCTrendBearish && + isPTrendBearish) + // + || + // + // Switching ... + (isCTrendSwitchedToBearish || + isPTrendSwitchedToBearish) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // SCORE Filter ... + + // + // VOLUME Filter ... + } + + // + // Detect Left Side of Box ... + XOHCL zoneLeftBar; + int idx = fromIDX + 1; + bool isBaseValid = true; + while (isBaseValid) + { + // + // Retrieve iteration Bar ... + has = zoneLeftBar.Init( + _Symbol, + _Period, + idx // + ); + if (!has) + { + // + zoneLeftBar.Clean(); + break; + } + + // + // Check Bar's Validation ... + + // + bool isBullishPassed = + isBullish && + zoneLeftBar.low >= zone.lower; + + // + bool isBearishPassed = + isBearish && + zoneLeftBar.high <= zone.upper; + + // + // Summarize Conditions ... + has = + isBullishPassed || + isBearishPassed; + if (!has) + { + break; + } + + // + idx++; + } + + // + // Ray to Left Side Zone, if Provided ... + if (rayLeft) + { + // + // Update Value ... + fromIDX = zone.FromIndex(); + + // + // Check Last Iteration Bar is Valid Bar ... + // then Update Zone from Time ... + has = zoneLeftBar.IsValid(); + if (has) + { + // + zone.from = zoneLeftBar.time; + fromIDX = zone.FromIndex(); + } + } + + // + // Draw Detected Zone ... + if (drawZones) + { + // + XCBoxObject *iZoneObj; + has = drawer.DrawBox( + zone, + iZoneObj // + ); + if (has) + { + // + ApplyStyle(iZoneObj, zone.dir); + + // + mObjects.Add(iZoneObj); + + // + // TODO: Enable This for Debugging ... + // string message = ToString(zone.dir) + " Zone Detected (" + cBar.time + ") ..."; + // Print(message); + } + ZeroMemory(iZoneObj); + } + + // + // Draw RR Tool ... + if (drawRRofZones) + { + // + double rr[]{ + 1, + 1.5, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 // + }; + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + has = iRRObj.CreateBoxRR( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + zone, + rr, + rrZoneLength // + ); + if (has) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + mObjects.Add(iRRObj); + } + ZeroMemory(iRRObj); + } + + // + // Handle Alerst ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (canAlert || canLogOnly) + { + // + string message = + zone.symbol + "," + + ToString(zone.period) + "> " + + ToString(zone.dir) + + " Zone Detected at: " + ToString(zone.to); + + // + if (canLogOnly) + { + alert.LogAlert(message); + } + else if (canAlert) + { + alert.SendAlert(message); + } + } + + // + // Cleanup Resources ... + + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + zoneLeftBar.Clean(); +} + +// +void ApplyStyle( + XCBoxObject *iObj, + ENUM_X_DIRECTION dir // +) +{ + // + if (!HasDirection(dir) || iObj == NULL) + { + return; + } + + // + int width = boxWidth > 0 + ? boxWidth + : 1; + int clr = IsBullish(dir) + ? bullishColor + : bearishColor; + + // + iObj.BoxColor(clr); + iObj.BoxWidth(width); + iObj.BoxStyle(boxStyle); + + // +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xdelta.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xdelta.mq5 new file mode 100644 index 0000000..9cadee6 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xdelta.mq5 @@ -0,0 +1,550 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Ocillator +// ------------------------------------------------- +// Name: X121 XDelta +// Description: Detect Comulative Volumes Delta ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XDelta Ocillator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XDELTA" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Makret ... +input group "Market"; +input int maLength = 14; // Moving Averge Length +input ENUM_X_MA_METHOD maMethod = X_MA_MODE_EMA; // Moving Averge Method + +// +// Presentation ... +input group "Presentation"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool showDeltaLine = true; // Show Delta Line +input bool showDeltaHistogram = true; // Show Delta Histogram +input bool showDeltaMa = true; // Show Delta Moving Average + +// +// Buffers Props ... + +// +#property indicator_separate_window + +// +#property indicator_buffers 6 +#property indicator_plots 3 + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 + +// +// Buffers ... + +// +#define deltaLineBufferIndex 0 +double deltaLineBuffer[]; + +#property indicator_label1 "Delta Line" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#define deltaHistogramBufferIndex 1 +double deltaHistogramBuffer[]; + +// +#define deltaHistogramColorBufferIndex 2 +double deltaHistogramColorBuffer[]; + +#property indicator_label2 "Delta Histogram" +#property indicator_type2 DRAW_COLOR_HISTOGRAM +#property indicator_color2 CLR_NONE, clrGreen, clrDarkRed +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +#define deltaMaBufferIndex 3 +double deltaMaBuffer[]; + +#property indicator_label3 "Delta MA" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrOrchid +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 3 + +// +#define rawDeltaBufferIndex mLastBufferIndex + 1 +double rawDeltaBuffer[]; + +// +#define deltaStateBufferIndex mLastBufferIndex + 2 +double deltaStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = maLength > 0 && + IsValid(maMethod); + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, maLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Delta Line ... + ENUM_DRAW_TYPE deltaLineDrawType = showDeltaLine ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(deltaLineBuffer, true); + SetIndexBuffer(deltaLineBufferIndex, deltaLineBuffer, INDICATOR_DATA); + PlotIndexSetDouble(deltaLineBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(deltaLineBufferIndex, PLOT_SHOW_DATA, showDeltaLine); + PlotIndexSetInteger(deltaLineBufferIndex, PLOT_DRAW_TYPE, deltaLineDrawType); + + // + // Delta Histogram ... + ENUM_DRAW_TYPE deltaHistogramDrawType = showDeltaHistogram ? DRAW_COLOR_HISTOGRAM : DRAW_NONE; + + // + ArraySetAsSeries(deltaHistogramBuffer, true); + SetIndexBuffer(deltaHistogramBufferIndex, deltaHistogramBuffer, INDICATOR_DATA); + PlotIndexSetDouble(deltaHistogramBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(deltaHistogramBufferIndex, PLOT_SHOW_DATA, showDeltaHistogram); + PlotIndexSetInteger(deltaHistogramBufferIndex, PLOT_DRAW_TYPE, deltaHistogramDrawType); + + // + ArraySetAsSeries(deltaHistogramColorBuffer, true); + SetIndexBuffer(deltaHistogramColorBufferIndex, deltaHistogramColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Delta Ma ... + ENUM_DRAW_TYPE deltaMaDrawType = showDeltaMa ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(deltaMaBuffer, true); + SetIndexBuffer(deltaMaBufferIndex, deltaMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(deltaMaBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(deltaMaBufferIndex, PLOT_SHOW_DATA, showDeltaMa); + PlotIndexSetInteger(deltaMaBufferIndex, PLOT_DRAW_TYPE, deltaMaDrawType); + + // + // Data Buffers ... + + // + ArraySetAsSeries(rawDeltaBuffer, true); + SetIndexBuffer(rawDeltaBufferIndex, rawDeltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaStateBuffer, true); + SetIndexBuffer(deltaStateBufferIndex, deltaStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + rawDeltaBuffer[barIndex] = 0.0; + deltaLineBuffer[barIndex] = 0.0; + deltaStateBuffer[barIndex] = 0.0; + deltaHistogramBuffer[barIndex] = 0.0; + deltaMaBuffer[barIndex] = 0.0; + deltaHistogramColorBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + XOHCL bar; + bool has = bar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!has) + { + return; + } + + // + double iDelta = 0.0; + + // + // Detecting Delta Volume ... + if (bar.IsBullish()) + { + iDelta = (double)bar.volume; + } + else if (bar.IsBearish()) + { + iDelta = -(double)bar.volume; + } + + // + // Setting iDelta Value ... + if (isFirstBar) + { + // + rawDeltaBuffer[bar_index] = iDelta; + deltaLineBuffer[bar_index] = iDelta; + deltaHistogramBuffer[bar_index] = iDelta; + } + else + { + // + iDelta += deltaLineBuffer[bar_index + 1]; + + // + rawDeltaBuffer[bar_index] = iDelta; + deltaLineBuffer[bar_index] = iDelta; + deltaHistogramBuffer[bar_index] = iDelta; + } + + // + // Setting iDelta State ... + double iState = iDelta > 0 + ? bullishColorIDX + : iDelta < 0 + ? bearishColorIDX + : hideColorIDX; + // + // Setting iDelta Color ... + double iDeltaColor = iDelta > 0 + ? bullishColorIDX + : iDelta < 0 + ? bearishColorIDX + : hideColorIDX; + + // + deltaStateBuffer[bar_index] = iState; + deltaHistogramColorBuffer[bar_index] = iDeltaColor; + + // + // Calculate Moving Averages ... + int deltaMAsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + maLength, + rawDeltaBuffer, + deltaMaBuffer, + maMethod // + ); + + // + bar.Clean(); +} + +// diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xdon.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xdon.mq5 new file mode 100644 index 0000000..49785d4 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xdon.mq5 @@ -0,0 +1,692 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XDON +// Description: XDON ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XDON Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XDON" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int donchainLength = 40; // Donchain Length + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showUpper = true; // Show Upper Band +input bool showLower = true; // Show Lower Band + +// +input bool showOpen = true; // Show Open +input bool showHigh = true; // Show High +input bool showClose = true; // Show Close +input bool showLow = true; // Show Low + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Plot Buffers ... + +// +// Open ... + +// +#define donOpenUpperBufferIndex 0 +double donOpenUpperBuffer[]; + +// +#define donOpenUpperPlotBufferIndex 0 +#property indicator_label1 "X121 O U" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrCornflowerBlue +#property indicator_width1 1 + +// +#define donOpenLowerBufferIndex 1 +double donOpenLowerBuffer[]; + +// +#define donOpenLowerPlotBufferIndex 1 +#property indicator_label2 "X121 O L" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrCornflowerBlue +#property indicator_width2 1 + +// +// High ... + +// +#define donHighUpperBufferIndex 2 +double donHighUpperBuffer[]; + +// +#define donHighUpperPlotBufferIndex 2 +#property indicator_label3 "X121 H U" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAquamarine +#property indicator_width3 1 + +// +#define donHighLowerBufferIndex 3 +double donHighLowerBuffer[]; + +// +#define donHighLowerPlotBufferIndex 3 +#property indicator_label4 "X121 H L" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAquamarine +#property indicator_width4 1 + +// +// Low ... + +// +#define donLowUpperBufferIndex 4 +double donLowUpperBuffer[]; + +// +#define donLowUpperPlotBufferIndex 4 +#property indicator_label5 "X121 L U" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrDarkOrchid +#property indicator_width5 1 + +// +#define donLowLowerBufferIndex 5 +double donLowLowerBuffer[]; + +// +#define donLowLowerPlotBufferIndex 5 +#property indicator_label6 "X121 L L" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrDarkOrchid +#property indicator_width6 1 + +// +// Close ... + +// +#define donCloseUpperBufferIndex 6 +double donCloseUpperBuffer[]; + +// +#define donCloseUpperPlotBufferIndex 6 +#property indicator_label7 "X121 C U" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCoral +#property indicator_width7 1 + +// +#define donCloseLowerBufferIndex 7 +double donCloseLowerBuffer[]; + +// +#define donCloseLowerPlotBufferIndex 7 +#property indicator_label8 "X121 C L" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCoral +#property indicator_width8 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 7; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + donchainLength > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + // + // Open ... + + // + // UPPER ... + bool canShowCOpenUpper = showUpper && showOpen; + ENUM_DRAW_TYPE donOpenUpperDrawType = canShowCOpenUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenUpperBuffer, true); + SetIndexBuffer(donOpenUpperBufferIndex, donOpenUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenUpper); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_DRAW_TYPE, donOpenUpperDrawType); + + // + // LOWER ... + bool canShowCOpenLower = showLower && showOpen; + ENUM_DRAW_TYPE donOpenLowerDrawType = canShowCOpenLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenLowerBuffer, true); + SetIndexBuffer(donOpenLowerBufferIndex, donOpenLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenLower); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_DRAW_TYPE, donOpenLowerDrawType); + + // + // Close ... + + // + // UPPER ... + bool canShowCCloseUpper = showUpper && showClose; + ENUM_DRAW_TYPE donCloseUpperDrawType = canShowCCloseUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseUpperBuffer, true); + SetIndexBuffer(donCloseUpperBufferIndex, donCloseUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseUpper); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_DRAW_TYPE, donCloseUpperDrawType); + + // + // LOWER ... + bool canShowCCloseLower = showLower && showClose; + ENUM_DRAW_TYPE donCloseLowerDrawType = canShowCCloseLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseLowerBuffer, true); + SetIndexBuffer(donCloseLowerBufferIndex, donCloseLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseLower); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_DRAW_TYPE, donCloseLowerDrawType); + + // + // High ... + + // + // UPPER ... + bool canShowCHighUpper = showUpper && showHigh; + ENUM_DRAW_TYPE donHighUpperDrawType = canShowCHighUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighUpperBuffer, true); + SetIndexBuffer(donHighUpperBufferIndex, donHighUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighUpper); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_DRAW_TYPE, donHighUpperDrawType); + + // + // LOWER ... + bool canShowCHighLower = showLower && showHigh; + ENUM_DRAW_TYPE donHighLowerDrawType = canShowCHighLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighLowerBuffer, true); + SetIndexBuffer(donHighLowerBufferIndex, donHighLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighLower); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_DRAW_TYPE, donHighLowerDrawType); + + // + // Low ... + + // + // UPPER ... + bool canShowCLowUpper = showUpper && showLow; + ENUM_DRAW_TYPE donLowUpperDrawType = canShowCLowUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowUpperBuffer, true); + SetIndexBuffer(donLowUpperBufferIndex, donLowUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowUpper); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_DRAW_TYPE, donLowUpperDrawType); + + // + // LOWER ... + bool canShowCLowLower = showLower && showLow; + ENUM_DRAW_TYPE donLowLowerDrawType = canShowCLowLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowLowerBuffer, true); + SetIndexBuffer(donLowLowerBufferIndex, donLowLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowLower); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_DRAW_TYPE, donLowLowerDrawType); + + // + // Data Buffers ... +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateDonchains( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + donOpenUpperBuffer[barIndex] = EMPTY_VALUE; + donOpenLowerBuffer[barIndex] = EMPTY_VALUE; + donCloseUpperBuffer[barIndex] = EMPTY_VALUE; + donCloseLowerBuffer[barIndex] = EMPTY_VALUE; + donHighUpperBuffer[barIndex] = EMPTY_VALUE; + donHighLowerBuffer[barIndex] = EMPTY_VALUE; + donLowUpperBuffer[barIndex] = EMPTY_VALUE; + donLowLowerBuffer[barIndex] = EMPTY_VALUE; +} + +/** + * Calculate Donchain ... + * + * @param bar_index: Integer, Bar Index ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Donchain Length ... + * @param _ouBuffer: Double Array Reference ... + * @param _olBuffer: Double Array Reference ... + * @param _huBuffer: Double Array Reference ... + * @param _hlBuffer: Double Array Reference ... + * @param _luBuffer: Double Array Reference ... + * @param _llBuffer: Double Array Reference ... + * @param _cuBuffer: Double Array Reference ... + * @param _clBuffer: Double Array Reference ... + */ +void CalculateDonchain( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + // + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, + // + double &_ouBuffer[], + double &_olBuffer[], + double &_huBuffer[], + double &_hlBuffer[], + double &_luBuffer[], + double &_llBuffer[], + double &_cuBuffer[], + double &_clBuffer[] // +) +{ + // + double iUpper = 0; + double iLower = 0; + + // + // OPEN ... + + // + int from = bar_index; + + // + iUpper = open[ArrayMaximum(open, from, _length)]; + iLower = open[ArrayMinimum(open, from, _length)]; + + // + _ouBuffer[bar_index] = iUpper; + _olBuffer[bar_index] = iLower; + + // + // HIGH ... + + // + iUpper = high[ArrayMaximum(high, from, _length)]; + iLower = high[ArrayMinimum(high, from, _length)]; + + // + _huBuffer[bar_index] = iUpper; + _hlBuffer[bar_index] = iLower; + + // + // LOW ... + + // + iUpper = low[ArrayMaximum(low, from, _length)]; + iLower = low[ArrayMinimum(low, from, _length)]; + + // + _luBuffer[bar_index] = iUpper; + _llBuffer[bar_index] = iLower; + + // + // CLOSE ... + + // + iUpper = close[ArrayMaximum(close, from, _length)]; + iLower = close[ArrayMinimum(close, from, _length)]; + + // + _cuBuffer[bar_index] = iUpper; + _clBuffer[bar_index] = iLower; +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateDonchains( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + CalculateDonchain( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume, + // + donchainLength, + // + donOpenUpperBuffer, + donOpenLowerBuffer, + donHighUpperBuffer, + donHighLowerBuffer, + donLowUpperBuffer, + donLowLowerBuffer, + donCloseUpperBuffer, + donCloseLowerBuffer // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xhk.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xhk.mq5 new file mode 100644 index 0000000..8e23e94 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xhk.mq5 @@ -0,0 +1,636 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XHK +// Description: XHK ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XHK Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XHK" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int xhkSmoothingLength = 14; // Length +input ENUM_X_MA_METHOD xhkSmoothingMode = X_MA_MODE_EMA; // Smoothing Method +input bool xhkIgnoreSmoothingShadows = false; // Ignore Smoothed Bar Shadows + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool drawRawXHKCandles = true; // Draw Raw Candle +input bool drawSmoothedXHKCandles = true; // Draw Smoothed Candle + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 2 + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +// PLOTTED Buffers ... + +// +#define openHKBufferIndex 0 +double openHKBuffer[]; + +// +#define highHKBufferIndex 1 +double highHKBuffer[]; + +// +#define lowHKBufferIndex 2 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex 3 +double closeHKBuffer[]; + +// +#define rawHKColorBufferIndex 4 +double rawHKColorBuffer[]; + +// +#define rawHKBufferIndex 0 +#property indicator_label1 "X121 XHK Open;X121 XHK High;X121 XHK Low;X121 XHK Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 CLR_NONE, clrDodgerBlue, clrDarkGoldenrod + +// +// Open ... +#define openBufferIndex 5 +double openBuffer[]; + +// +// High ... +#define highBufferIndex 6 +double highBuffer[]; + +// +// Low ... +#define lowBufferIndex 7 +double lowBuffer[]; + +// +// Close ... +#define closeBufferIndex 8 +double closeBuffer[]; + +// +// Candle Color ... +#define candleColorBufferIndex 9 +double candleColorBuffer[]; + +// +#define candlesBufferIndex 1 +#property indicator_label2 "X121 XHKSM Open;X121 XHKSM High;X121 XHKSM Low;X121 XHKSM Close" +#property indicator_type2 DRAW_COLOR_CANDLES +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + true + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, xhkSmoothingLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + + // + // RAW ... + + // + // Raw Candles Color ... + ArraySetAsSeries(rawHKColorBuffer, true); + SetIndexBuffer(rawHKColorBufferIndex, rawHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(rawHKBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rawHKBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + + // + // SMOOTHED ... + + // + // Candles Color ... + ArraySetAsSeries(candleColorBuffer, true); + SetIndexBuffer(candleColorBufferIndex, candleColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(candlesBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(candlesBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateXHK( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + lowHKBuffer[barIndex] = 0.0; + openHKBuffer[barIndex] = 0.0; + highHKBuffer[barIndex] = 0.0; + closeHKBuffer[barIndex] = 0.0; + rawHKColorBuffer[barIndex] = hideColorIDX; + + // + lowBuffer[barIndex] = 0.0; + openBuffer[barIndex] = 0.0; + highBuffer[barIndex] = 0.0; + closeBuffer[barIndex] = 0.0; + candleColorBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate ATR Zones ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateXHK( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + double mPrevHKOpenValue; + double mPrevHKCloseValue; + + // + if (ArraySize(open) <= bar_index + 1) + { + // + mPrevHKOpenValue = 0; + mPrevHKCloseValue = 0; + } + else + { + // + mPrevHKOpenValue = openHKBuffer[bar_index + 1]; + mPrevHKCloseValue = closeHKBuffer[bar_index + 1]; + } + + // + double mHKOpenValue = (mPrevHKOpenValue + mPrevHKCloseValue) / 2; + double mHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double mHKHighValue = MathMax(high[bar_index], MathMax(mHKOpenValue, mHKCloseValue)); + double mHKLowValue = MathMin(low[bar_index], MathMin(mHKOpenValue, mHKCloseValue)); + + // + double candleColorValue = + mHKOpenValue < mHKCloseValue ? bullishColorIDX : bearishColorIDX; + + // + // Raw HK Buffers ... + openHKBuffer[bar_index] = mHKOpenValue; + highHKBuffer[bar_index] = mHKHighValue; + lowHKBuffer[bar_index] = mHKLowValue; + closeHKBuffer[bar_index] = mHKCloseValue; + rawHKColorBuffer[bar_index] = drawRawXHKCandles ? candleColorValue : hideColorIDX; + + // + // Apply Smoothing ... + bool canSmooth = xhkSmoothingLength > 0 && + xhkSmoothingMode != X_MA_MODE_NONE; + if (!canSmooth) + { + // + double min = MathMin(mHKOpenValue, mHKCloseValue); + double max = MathMax(mHKOpenValue, mHKCloseValue); + + // + openBuffer[bar_index] = mHKOpenValue; + highBuffer[bar_index] = xhkIgnoreSmoothingShadows ? max : mHKHighValue; + lowBuffer[bar_index] = xhkIgnoreSmoothingShadows ? min : mHKLowValue; + closeBuffer[bar_index] = mHKCloseValue; + candleColorBuffer[bar_index] = drawSmoothedXHKCandles ? candleColorValue : hideColorIDX; + } + else + { + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + openHKBuffer, + openBuffer, + xhkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + closeHKBuffer, + closeBuffer, + xhkSmoothingMode // + ); + + // + // Ignoring Shadows ... + if (!xhkIgnoreSmoothingShadows) + { + // + // High ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + highHKBuffer, + highBuffer, + xhkSmoothingMode // + ); + + // + // Low ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + lowHKBuffer, + lowBuffer, + xhkSmoothingMode // + ); + } + else + { + // + double min = MathMin(closeBuffer[bar_index], openBuffer[bar_index]); + double max = MathMin(closeBuffer[bar_index], openBuffer[bar_index]); + + // + lowBuffer[bar_index] = min; + highBuffer[bar_index] = max; + } + + // + // Calculate Smoothed Color ... + candleColorValue = + openBuffer[bar_index] < closeBuffer[bar_index] ? bullishColorIDX : bearishColorIDX; + candleColorBuffer[bar_index] = drawSmoothedXHKCandles ? candleColorValue : hideColorIDX; + } +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xich.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xich.mq5 new file mode 100644 index 0000000..89b3fb8 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xich.mq5 @@ -0,0 +1,625 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XICH" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input ENUM_X_PRICE chikouSpanMode = X_PRICE_CLOSE; // ChikouSpan Mode +input int tenkanSenLength = 9; // TenkanSen Length +input ENUM_X_BOUNDARY_PRICE tenkanSenMode = X_BOUNDARY_PRICE_HIGH_LOW; // TencanSen Mode +input int kijunSenLength = 26; // KijunSen Length +input ENUM_X_BOUNDARY_PRICE kijunSenMode = X_BOUNDARY_PRICE_HIGH_LOW; // KijunSen Mode +input int senkouSpanBLength = 52; // SenkouSpan B Length +input ENUM_X_BOUNDARY_PRICE senkouSpanBMode = X_BOUNDARY_PRICE_HIGH_LOW; // SenkouSpan B Mode + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool shiftKumo = true; // Shift Kumo +input bool showTenkanSen = true; // Show TenkanSen +input bool showKijunSen = true; // Show KijunSen +input bool showChikouSpan = true; // Show ChikouSpan +input bool showSenkouSpanA = true; // Show Senkou Span A +input bool showSenkouSpanB = true; // Show Senkou Span B +input bool showKumo = true; // Show Kumo + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 6 + +// +// Plot Buffers ... + +// +#define tenkanSenBufferIndex 0 +double tenkanSenBuffer[]; + +// +#property indicator_label1 "XICH TK" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +#define kijunSenBufferIndex 1 +double kijunSenBuffer[]; + +// +#property indicator_label2 "XICH KJ" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrDodgerBlue +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +#define chikouSpanBufferIndex 2 +double chikouSpanBuffer[]; + +// +#property indicator_label3 "XICH CS" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrDarkGreen +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +#define senkouSpanABufferIndex 3 +double senkouSpanABuffer[]; + +// +#property indicator_label4 "XICH SSA" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLightGray +#property indicator_style4 STYLE_DASHDOTDOT +#property indicator_width4 2 + +// +#define senkouSpanBBufferIndex 4 +double senkouSpanBBuffer[]; + +// +#property indicator_label5 "XICH SSB" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrLightGray +#property indicator_style5 STYLE_DASHDOTDOT +#property indicator_width5 2 + +// +#define senkouABufferIndex 5 +double senkouABuffer[]; + +// +#define senkouBBufferIndex 6 +double senkouBBuffer[]; + +// +#define kumoBufferIndex 5 + +// +#property indicator_label6 "XICH Kumo" +#property indicator_type6 DRAW_FILLING +#property indicator_color6 clrAqua, clrMagenta +#property indicator_style6 STYLE_SOLID +#property indicator_width6 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 6; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + kijunSenLength > 0 && + tenkanSenLength > 0 && + senkouSpanBLength > 0 && + IsValid(kijunSenMode) && + IsValid(tenkanSenMode) && + IsValid(chikouSpanMode) && + IsValid(senkouSpanBMode) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(kijunSenLength, tenkanSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE tenkanSenDrawType = showTenkanSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tenkanSenBuffer, true); + SetIndexBuffer(tenkanSenBufferIndex, tenkanSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_SHOW_DATA, showTenkanSen); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_TYPE, tenkanSenDrawType); + + // + ENUM_DRAW_TYPE kijunSenDrawType = showKijunSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenBuffer, true); + SetIndexBuffer(kijunSenBufferIndex, kijunSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_SHOW_DATA, showKijunSen); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_TYPE, kijunSenDrawType); + + // + ENUM_DRAW_TYPE chikouSpanDrawType = showChikouSpan ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(chikouSpanBuffer, true); + SetIndexBuffer(chikouSpanBufferIndex, chikouSpanBuffer, INDICATOR_DATA); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHOW_DATA, showChikouSpan); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_TYPE, chikouSpanDrawType); + + // + int shiftSize = shiftKumo ? kijunSenLength : 0; + + // + ENUM_DRAW_TYPE senkouSpanADrawType = showSenkouSpanA ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(senkouSpanABuffer, true); + SetIndexBuffer(senkouSpanABufferIndex, senkouSpanABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_SHOW_DATA, showSenkouSpanA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_DRAW_TYPE, senkouSpanADrawType); + + // + ENUM_DRAW_TYPE senkouSpanBDrawType = showSenkouSpanB ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(senkouSpanBBuffer, true); + SetIndexBuffer(senkouSpanBBufferIndex, senkouSpanBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_SHOW_DATA, showSenkouSpanB); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_DRAW_TYPE, senkouSpanBDrawType); + + // + ArraySetAsSeries(senkouABuffer, true); + SetIndexBuffer(senkouABufferIndex, senkouABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + ArraySetAsSeries(senkouBBuffer, true); + SetIndexBuffer(senkouBBufferIndex, senkouBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + ENUM_DRAW_TYPE kumoDrawType = showKumo ? DRAW_FILLING : DRAW_NONE; + + // + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kumoBufferIndex, PLOT_DRAW_TYPE, kumoDrawType); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + senkouABuffer[barIndex] = 0; + senkouBBuffer[barIndex] = 0; + kijunSenBuffer[barIndex] = 0; + tenkanSenBuffer[barIndex] = 0; + chikouSpanBuffer[barIndex] = 0; + senkouSpanABuffer[barIndex] = 0; + senkouSpanBBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double uppers[]; + double lowers[]; + + // + double uppersMax = 0; + double uppersMin = 0; + + // + double lowersMax = 0; + double lowersMin = 0; + + // + // Calculate ChikouSpan ... + double iChikouSpan = GetAppliedPrice( + _Symbol, + _Period, + bar_index, + chikouSpanMode // + ); + + // + // Calculate TenkanSen ... + GetPriceBoundary( + uppers, + lowers, + _Symbol, + _Period, + tenkanSenMode, + tenkanSenLength, + bar_index // + ); + + // + uppersMax = uppers[ArrayMaximum(uppers)]; + uppersMin = uppers[ArrayMinimum(uppers)]; + + // + lowersMax = lowers[ArrayMaximum(lowers)]; + lowersMin = lowers[ArrayMinimum(lowers)]; + + // + double iTenkanSen = (uppersMax + lowersMin) / 2; + + // + // Calculate KijunSen ... + GetPriceBoundary( + uppers, + lowers, + _Symbol, + _Period, + kijunSenMode, + kijunSenLength, + bar_index // + ); + + // + uppersMax = uppers[ArrayMaximum(uppers)]; + uppersMin = uppers[ArrayMinimum(uppers)]; + + // + lowersMax = lowers[ArrayMaximum(lowers)]; + lowersMin = lowers[ArrayMinimum(lowers)]; + + // + double iKijunSen = (uppersMax + lowersMin) / 2; + + // + // Calculate SenkouSpanB ... + GetPriceBoundary( + uppers, + lowers, + _Symbol, + _Period, + senkouSpanBMode, + senkouSpanBLength, + bar_index // + ); + + // + uppersMax = uppers[ArrayMaximum(uppers)]; + uppersMin = uppers[ArrayMinimum(uppers)]; + + // + lowersMax = lowers[ArrayMaximum(lowers)]; + lowersMin = lowers[ArrayMinimum(lowers)]; + + // + double iSenkouSpanB = (uppersMax + lowersMin) / 2; + + // + // Calculate SenkouSpanA ... + double iSenkouSpanA = (iTenkanSen + iKijunSen) / 2; + + // + // Setting Buffers ... + kijunSenBuffer[bar_index] = iKijunSen; + senkouABuffer[bar_index] = iSenkouSpanA; + senkouBBuffer[bar_index] = iSenkouSpanB; + tenkanSenBuffer[bar_index] = iTenkanSen; + chikouSpanBuffer[bar_index] = iChikouSpan; + senkouSpanABuffer[bar_index] = iSenkouSpanA; + senkouSpanBBuffer[bar_index] = iSenkouSpanB; +} + +// diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xoscs.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xoscs.mq5 new file mode 100644 index 0000000..4c32077 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xoscs.mq5 @@ -0,0 +1,1026 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_X3MA" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Accumulation/Distribution"; +input ENUM_APPLIED_VOLUME adAppliedTo = VOLUME_TICK; // Applied To + +// +input group "ADX"; +input int adxLength = 14; // Length + +// +input group "ATR"; +input int atrLength = 14; // Length + +// +input group "CCI"; +input int cciLength = 14; // Length +input ENUM_APPLIED_PRICE cciAppliedTo = PRICE_TYPICAL; // Applied To + +// +input group "RSI"; +input int rsiLength = 14; // Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "MFI"; +input int mfiLength = 14; // Length +input ENUM_APPLIED_VOLUME mfiAppliedTo = VOLUME_TICK; // Applied To + +// +input group "RVI"; +input int rviLength = 14; // Length + +// +input group "MACD"; +input int macdFastLength = 12; // Fast EMA Length +input int macdSlowLength = 26; // Slow EMA Length +input int macdSignalLength = 9; // Signal Length +input ENUM_APPLIED_PRICE macdAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Momentum"; +input int momentumLength = 14; // Length +input ENUM_APPLIED_PRICE momentumAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Stochastic"; +input int stochasticKLength = 5; // K Length (Bars for Calculation) +input int stochasticDLength = 3; // D Length (first Smoothing) +input int stochasticSmoothingLength = 3; // Smoothing Length +input ENUM_MA_METHOD stochasticSmoothingMethod = MODE_SMA; // Smoothing Method +input ENUM_STO_PRICE stochasticAppliedTo = STO_LOWHIGH; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +// Buffers ... + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 16 +#property indicator_plots 0 + +// +// Plot Buffers ... + +// +// Data Buffers ... + +// +int mLastBufferIndex = -1; + +// +// AC ... +#define acBufferIndex mLastBufferIndex + 1 +double acBuffer[]; + +// +// AD ... +#define adBufferIndex mLastBufferIndex + 2 +double adBuffer[]; + +// +// ADX ... +#define adxBufferIndex mLastBufferIndex + 3 +double adxBuffer[]; + +// +// ADX Plus ... +#define adxpBufferIndex mLastBufferIndex + 4 +double adxpBuffer[]; + +// +// ADX Negative ... +#define adxnBufferIndex mLastBufferIndex + 5 +double adxnBuffer[]; + +// +// ATR ... +#define atrBufferIndex mLastBufferIndex + 6 +double atrBuffer[]; + +// +// CCI ... +#define cciBufferIndex mLastBufferIndex + 7 +double cciBuffer[]; + +// +// RSI ... +#define rsiBufferIndex mLastBufferIndex + 8 +double rsiBuffer[]; + +// +// MFI ... +#define mfiBufferIndex mLastBufferIndex + 9 +double mfiBuffer[]; + +// +// RVI ... +#define rviBufferIndex mLastBufferIndex + 10 +double rviBuffer[]; + +// +// RVI Signal ... +#define rviSignalBufferIndex mLastBufferIndex + 11 +double rviSignalBuffer[]; + +// +// MACD ... +#define macdBufferIndex mLastBufferIndex + 12 +double macdBuffer[]; + +// +// MACD Signal ... +#define macdSignalBufferIndex mLastBufferIndex + 13 +double macdSignalBuffer[]; + +// +// Momentum ... +#define momentumBufferIndex mLastBufferIndex + 14 +double momentumBuffer[]; + +// +// Stochstic ... +#define stochasticBufferIndex mLastBufferIndex + 15 +double stochasticBuffer[]; + +// +// Stochstic Signal ... +#define stochasticSignalBufferIndex mLastBufferIndex + 16 +double stochasticSignalBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int acHandler = INVALID_HANDLE; +int adHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int atrHandler = INVALID_HANDLE; +int cciHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int rviHandler = INVALID_HANDLE; +int mfiHandler = INVALID_HANDLE; +int macdHandler = INVALID_HANDLE; +int momentumHandler = INVALID_HANDLE; +int stochasticHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + if (!InitializeHandlres()) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + DeInitializeHandlres(); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // AC ... + int acCalculatedBars = BarsCalculated(acHandler); + + // + // AD ... + int adCalculatedBars = BarsCalculated(adHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // CCI ... + int cciCalculatedBars = BarsCalculated(cciHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // MFI ... + int mfiCalculatedBars = BarsCalculated(mfiHandler); + + // + // RVI ... + int rviCalculatedBars = BarsCalculated(rviHandler); + + // + // MACD ... + int macdCalculatedBars = BarsCalculated(macdHandler); + + // + // Momentum ... + int momentumCalculatedBars = BarsCalculated(momentumHandler); + + // + // Stochastic ... + int stochasticCalculatedBars = BarsCalculated(stochasticHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // AC ... + acCalculatedBars >= maxLength && + // + // AD ... + adCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // CCI ... + cciCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // MFI ... + mfiCalculatedBars >= maxLength && + // + // RVI ... + rviCalculatedBars >= maxLength && + // + // MACD ... + macdCalculatedBars >= maxLength && + // + // Momentum ... + momentumCalculatedBars >= maxLength && + // + // Stochastic ... + stochasticCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // AC ... + int copiedACs = CopyBuffer(acHandler, MAIN_LINE, 0, limit, acBuffer); + + // + // AD ... + int copiedADs = CopyBuffer(adHandler, MAIN_LINE, 0, limit, adBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // ATR ... + int copiedATRs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // CCI ... + int copiedCCIs = CopyBuffer(cciHandler, MAIN_LINE, 0, limit, cciBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // MFI ... + int copiedMFIs = CopyBuffer(mfiHandler, MAIN_LINE, 0, limit, mfiBuffer); + + // + // RVI ... + int copiedRVIs = CopyBuffer(rviHandler, MAIN_LINE, 0, limit, rviBuffer); + + // + // RVI ... + int copiedRVISignals = CopyBuffer(rviHandler, SIGNAL_LINE, 0, limit, rviSignalBuffer); + + // + // MACD ... + int copiedMACDs = CopyBuffer(macdHandler, MAIN_LINE, 0, limit, macdBuffer); + + // + // MACD Signal ... + int copiedMACDSignals = CopyBuffer(macdHandler, SIGNAL_LINE, 0, limit, macdSignalBuffer); + + // + // Momentum ... + int copiedMomentums = CopyBuffer(cciHandler, MAIN_LINE, 0, limit, momentumBuffer); + + // + // Stochastic ... + int copiedStochastics = CopyBuffer(stochasticHandler, MAIN_LINE, 0, limit, stochasticBuffer); + + // + // Stochastic Signal ... + int copiedStochasticSignals = CopyBuffer(stochasticHandler, SIGNAL_LINE, 0, limit, stochasticSignalBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // AC ... + copiedACs > 0 && + // + // AD ... + copiedADs > 0 && + // + // ADX ... + copiedADXs > 0 && + // + // ADX Plus ... + copiedADXPs > 0 && + // + // ADX Negative ... + copiedADXNs > 0 && + // + // ATR ... + copiedATRs > 0 && + // + // CCI ... + copiedCCIs > 0 && + // + // RSI ... + copiedRSIs > 0 && + // + // MFI ... + copiedMFIs > 0 && + // + // RVI ... + copiedRVIs > 0 && + // + // RVI Signal ... + copiedRVISignals > 0 && + // + // MACD ... + copiedMACDs > 0 && + // + // MACD Signal ... + copiedMACDSignals > 0 && + // + // Momentum ... + copiedMomentums > 0 && + // + // Stochastic ... + copiedStochastics > 0 && + // + // Stochastic Signal ... + copiedStochasticSignals > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + adxLength > 0 && + atrLength > 0 && + cciLength > 0 && + rsiLength > 0 && + mfiLength > 0 && + rviLength > 0 && + // + macdFastLength > 0 && + macdSlowLength > 0 && + macdSignalLength > 0 && + macdFastLength < macdSlowLength && + // + stochasticKLength > 0 && + stochasticDLength > 0 && + stochasticSmoothingLength > 0 && + // + momentumLength > 0 + // + ; + + // + return result; +} + +/** + * Initialize All Indicators Handlers ... + * + * @return ( bool ) + */ +bool InitializeHandlres() +{ + // + bool result = false; + + // + // AC ... + acHandler = iAC(_Symbol, _Period); + result = acHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // AD ... + adHandler = iAD( + _Symbol, + _Period, + adAppliedTo // + ); + result = adHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // CCI ... + cciHandler = iCCI( + _Symbol, + _Period, + cciLength, + cciAppliedTo // + ); + result = cciHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MFI ... + mfiHandler = iMFI( + _Symbol, + _Period, + mfiLength, + mfiAppliedTo // + ); + result = mfiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RVI ... + rviHandler = iRVI( + _Symbol, + _Period, + rviLength // + ); + result = rviHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MACD ... + macdHandler = iMACD( + _Symbol, + _Period, + macdFastLength, + macdSlowLength, + macdSignalLength, + macdAppliedTo // + ); + result = macdHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Momentum ... + momentumHandler = iMomentum( + _Symbol, + _Period, + momentumLength, + momentumAppliedTo // + ); + result = momentumHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Stochastic ... + stochasticHandler = iStochastic( + _Symbol, + _Period, + stochasticKLength, + stochasticDLength, + stochasticSmoothingLength, + stochasticSmoothingMethod, + stochasticAppliedTo // + ); + result = stochasticHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; +} + +/** + * Release All Indicators ... + */ +void DeInitializeHandlres() +{ + // + IndicatorRelease(acHandler); + IndicatorRelease(adHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(cciHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(mfiHandler); + IndicatorRelease(rviHandler); + IndicatorRelease(macdHandler); + IndicatorRelease(momentumHandler); + IndicatorRelease(stochasticHandler); +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(adxLength, atrLength); + result = MathMax(result, cciLength); + result = MathMax(result, rsiLength); + result = MathMax(result, mfiLength); + result = MathMax(result, rviLength); + result = MathMax(result, momentumLength); + result = MathMax(result, macdFastLength); + result = MathMax(result, macdSlowLength); + result = MathMax(result, macdSignalLength); + result = MathMax(result, stochasticKLength); + result = MathMax(result, stochasticDLength); + result = MathMax(result, stochasticSmoothingLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Data Buffers ... + + // + // AC ... + ArraySetAsSeries(acBuffer, true); + SetIndexBuffer(acBufferIndex, acBuffer, INDICATOR_CALCULATIONS); + + // + // AD ... + ArraySetAsSeries(adBuffer, true); + SetIndexBuffer(adBufferIndex, adBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + // ADX Plus ... + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + // ADX Negative ... + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + // CCI ... + ArraySetAsSeries(cciBuffer, true); + SetIndexBuffer(cciBufferIndex, cciBuffer, INDICATOR_CALCULATIONS); + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // MFI ... + ArraySetAsSeries(mfiBuffer, true); + SetIndexBuffer(mfiBufferIndex, mfiBuffer, INDICATOR_CALCULATIONS); + + // + // RVI ... + ArraySetAsSeries(rviBuffer, true); + SetIndexBuffer(rviBufferIndex, rviBuffer, INDICATOR_CALCULATIONS); + + // + // RVI Signal ... + ArraySetAsSeries(rviSignalBuffer, true); + SetIndexBuffer(rviSignalBufferIndex, rviSignalBuffer, INDICATOR_CALCULATIONS); + + // + // MACD ... + ArraySetAsSeries(macdBuffer, true); + SetIndexBuffer(macdBufferIndex, macdBuffer, INDICATOR_CALCULATIONS); + + // + // MACD Signal ... + ArraySetAsSeries(macdSignalBuffer, true); + SetIndexBuffer(macdSignalBufferIndex, macdSignalBuffer, INDICATOR_CALCULATIONS); + + // + // Momentum ... + ArraySetAsSeries(momentumBuffer, true); + SetIndexBuffer(momentumBufferIndex, momentumBuffer, INDICATOR_CALCULATIONS); + + // + // Stochastics ... + ArraySetAsSeries(stochasticBuffer, true); + SetIndexBuffer(stochasticBufferIndex, stochasticBuffer, INDICATOR_CALCULATIONS); + + // + // Stochastics Signal ... + ArraySetAsSeries(stochasticSignalBuffer, true); + SetIndexBuffer(stochasticSignalBufferIndex, stochasticSignalBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + acBuffer[barIndex] = emptyValue; + adBuffer[barIndex] = emptyValue; + adxBuffer[barIndex] = emptyValue; + adxpBuffer[barIndex] = emptyValue; + adxnBuffer[barIndex] = emptyValue; + atrBuffer[barIndex] = emptyValue; + cciBuffer[barIndex] = emptyValue; + rsiBuffer[barIndex] = emptyValue; + mfiBuffer[barIndex] = emptyValue; + rviBuffer[barIndex] = emptyValue; + macdBuffer[barIndex] = emptyValue; + momentumBuffer[barIndex] = emptyValue; + rviSignalBuffer[barIndex] = emptyValue; + macdSignalBuffer[barIndex] = emptyValue; + stochasticBuffer[barIndex] = emptyValue; + stochasticSignalBuffer[barIndex] = emptyValue; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Implement Colorify Mechanism ... +} + +// diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xstr.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xstr.mq5 new file mode 100644 index 0000000..3a95d4d --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xstr.mq5 @@ -0,0 +1,812 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XSTR +// Description: XSTR ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XSTR Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XSTR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int strLength = 14; // Length +input double strMultiplier = 3; // Multiplier +input int vidyaLength = 14; // Smothing Length +input ENUM_MA_METHOD strBoundaryMode = MODE_SMA; // Boundary Mode +input ENUM_APPLIED_PRICE strAppliedTo = PRICE_MEDIAN; // Applied To +input ENUM_APPLIED_PRICE vidyaAppliedTo = PRICE_CLOSE; // Smoothing Applied To + +// +input group "Presentation"; +input bool showStr = true; // Show Str +input bool showVidya = true; // Show Vidya +input bool showStrUpper = true; // Show Str Upper +input bool showStrLower = true; // Show Str Lower +input bool showStrLowMa = true; // Show Low Smoothed Buffer +input bool showStrHighMa = true; // Show High Smoothed Buffer + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 6 + +// +// STR ... +#define strBufferIndex 0 +double strBuffer[]; + +#define strColorBufferIndex 1 +double strColorBuffer[]; + +// +#define strPlotBufferIndex 0 +#property indicator_label1 "X121 STR" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// Up ... +#define strUpBufferIndex 2 +double strUpBuffer[]; + +// +#define strUpPlotBufferIndex 1 +#property indicator_label2 "X121 STR U" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrBlueViolet +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// Down ... +#define strDownBufferIndex 3 +double strDownBuffer[]; + +// +#define strDownPlotBufferIndex 2 +#property indicator_label3 "X121 STR D" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrBlueViolet +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// High MA ... +#define strHighMaBufferIndex 4 +double strHighMaBuffer[]; + +// +#define strHighMaPlotBufferIndex 3 +#property indicator_label4 "X121 STR HSM" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAqua +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Low Ma ... +#define strLowMaBufferIndex 5 +double strLowMaBuffer[]; + +// +#define strLowMaPlotBufferIndex 4 +#property indicator_label5 "X121 STR LSM" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrMagenta +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +// VIDYA ... +#define vidyaBufferIndex 6 +double vidyaBuffer[]; + +// +#define vidyaPlotBufferIndex 5 +#property indicator_label6 "X121 VIDYA" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 6; + +// +// STR ... + +// +// Atr ... +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +// Price ... +#define strPriceBufferIndex mLastBufferIndex + 2 +double strPriceBuffer[]; + +// +// Trend ... +#define strStateBufferIndex mLastBufferIndex + 3 +double strStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +// MA Handler ... +int lowMaHandler = INVALID_HANDLE; +int highMaHandler = INVALID_HANDLE; +int vidyaHandler = INVALID_HANDLE; + +// +bool isStrTrendChanged; +bool isStrStartBearishTrend; +bool isStrStartBullishTrend; + +// +int changeOfTrend; +int startBearishTrend; +int startBullishTrend; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + strLength // + ); + bool isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // Low Ma ... + lowMaHandler = iMA( + _Symbol, + _Period, + strLength, + 0, + strBoundaryMode, + PRICE_LOW // + ); + isInited = lowMaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // High Ma ... + highMaHandler = iMA( + _Symbol, + _Period, + strLength, + 0, + strBoundaryMode, + PRICE_HIGH // + ); + isInited = highMaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // Vidya ... + vidyaHandler = iVIDyA( + _Symbol, + _Period, + strLength, + vidyaLength, + 0, // Shift ... + vidyaAppliedTo // + ); + isInited = vidyaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(atrHandler); + IndicatorRelease(vidyaHandler); + IndicatorRelease(lowMaHandler); + IndicatorRelease(highMaHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // VIDYA ... + int vidyaCalculatedBars = BarsCalculated(vidyaHandler); + + // + // Low Ma ... + int lowMaCalculatedBars = BarsCalculated(lowMaHandler); + + // + // High Ma ... + int highMaCalculatedBars = BarsCalculated(highMaHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= 0 && + // + // VIDYA ... + vidyaCalculatedBars >= 0 && + // + // Low Ma ... + lowMaCalculatedBars >= 0 && + // + // High Ma ... + highMaCalculatedBars >= 0 + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + // + // checking for the limit start of calculation of an indicator ... + limit = + (prev_calculated > rates_total || prev_calculated <= 0) + ? maxLength + : prev_calculated - 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, rates_total, atrBuffer); + + // + // VYDIA ... + int copiedVidyas = CopyBuffer(vidyaHandler, 0, 0, rates_total, vidyaBuffer); + + // + // Low Ma ... + int copiedLowMas = CopyBuffer(lowMaHandler, 0, 0, rates_total, strLowMaBuffer); + + // + // High Ma ... + int copiedHighMas = CopyBuffer(highMaHandler, 0, 0, rates_total, strHighMaBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= 0 && + // + // VIDYA ... + copiedVidyas >= 0 && + // + // Low Ma ... + copiedLowMas >= 0 && + // + // Hig Ma ... + copiedHighMas >= 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + // STR ... + strLength > 0 && + strMultiplier > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(1, strLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // STR ... + SetIndexBuffer(strBufferIndex, strBuffer, INDICATOR_DATA); + SetIndexBuffer(strColorBufferIndex, strColorBuffer, INDICATOR_COLOR_INDEX); + + // + ENUM_DRAW_TYPE strUpDrawType = showStrUpper ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strUpBufferIndex, strUpBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strUpPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strUpPlotBufferIndex, PLOT_SHOW_DATA, showStrUpper); + PlotIndexSetInteger(strUpPlotBufferIndex, PLOT_DRAW_TYPE, strUpDrawType); + + // + ENUM_DRAW_TYPE strDownDrawType = showStrLower ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strDownBufferIndex, strDownBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strDownPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strDownPlotBufferIndex, PLOT_SHOW_DATA, showStrLower); + PlotIndexSetInteger(strDownPlotBufferIndex, PLOT_DRAW_TYPE, strDownDrawType); + + // + ENUM_DRAW_TYPE strLowMaDrawType = showStrLowMa ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strLowMaBufferIndex, strLowMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strLowMaPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strLowMaPlotBufferIndex, PLOT_SHOW_DATA, showStrLowMa); + PlotIndexSetInteger(strLowMaPlotBufferIndex, PLOT_DRAW_TYPE, strLowMaDrawType); + + // + ENUM_DRAW_TYPE strHighMaDrawType = showStrHighMa ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strHighMaBufferIndex, strHighMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strHighMaPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strHighMaPlotBufferIndex, PLOT_SHOW_DATA, showStrHighMa); + PlotIndexSetInteger(strHighMaPlotBufferIndex, PLOT_DRAW_TYPE, strHighMaDrawType); + + // + ENUM_DRAW_TYPE vidyaDrawType = showVidya ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(vidyaBufferIndex, vidyaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(vidyaPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(vidyaPlotBufferIndex, PLOT_SHOW_DATA, showVidya); + PlotIndexSetInteger(vidyaPlotBufferIndex, PLOT_DRAW_TYPE, vidyaDrawType); + + // + // Data Buffers ... + + // + SetIndexBuffer(strPriceBufferIndex, strPriceBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(strStateBufferIndex, strStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + CalculateStr( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // STR ... + strBuffer[barIndex] = emptyValue; + strUpBuffer[barIndex] = emptyValue; + strDownBuffer[barIndex] = emptyValue; + strPriceBuffer[barIndex] = emptyValue; + strLowMaBuffer[barIndex] = emptyValue; + strHighMaBuffer[barIndex] = emptyValue; + + // + strColorBuffer[barIndex] = hideColorIDX; + strStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate STR ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateStr( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + // Calculated Price ... + ENUM_X_PRICE mPType = ToXPrice(strAppliedTo); + double price = GetAppliedPrice( + mPType, + open, + high, + low, + close, + bar_index // + ); + strPriceBuffer[bar_index] = price; + + // + double atr = atrBuffer[bar_index]; + + // + // Up ... + strUpBuffer[bar_index] = price + (strMultiplier * atr); + + // + // Down ... + strDownBuffer[bar_index] = price - (strMultiplier * atr); + + // + if (close[bar_index] > strUpBuffer[bar_index - 1]) + { + // + strStateBuffer[bar_index] = 1; + if (strStateBuffer[bar_index - 1] == -1) + { + changeOfTrend = 1; + } + } + else if (close[bar_index] < strDownBuffer[bar_index - 1]) + { + // + strStateBuffer[bar_index] = -1; + if (strStateBuffer[bar_index - 1] == 1) + { + changeOfTrend = 1; + } + } + else if (strStateBuffer[bar_index - 1] == 1) + { + // + strStateBuffer[bar_index] = 1; + changeOfTrend = 0; + } + else if (strStateBuffer[bar_index - 1] == -1) + { + // + strStateBuffer[bar_index] = -1; + changeOfTrend = 0; + } + + // + // Down Trend Starting ... + if (strStateBuffer[bar_index] < 0 && strStateBuffer[bar_index - 1] > 0) + { + startBearishTrend = 1; + } + else + { + startBearishTrend = 0; + } + + // + // Up Trend Starting ... + if (strStateBuffer[bar_index] > 0 && strStateBuffer[bar_index - 1] < 0) + { + startBullishTrend = 1; + } + else + { + startBullishTrend = 0; + } + + // + if (strStateBuffer[bar_index] > 0 && strDownBuffer[bar_index] < strDownBuffer[bar_index - 1]) + { + strDownBuffer[bar_index] = strDownBuffer[bar_index - 1]; + } + + // + if (strStateBuffer[bar_index] < 0 && strUpBuffer[bar_index] > strUpBuffer[bar_index - 1]) + { + strUpBuffer[bar_index] = strUpBuffer[bar_index - 1]; + } + + // + if (startBearishTrend == 1) + { + strUpBuffer[bar_index] = strPriceBuffer[bar_index] + (strMultiplier * atr); + } + + // + if (startBullishTrend == 1) + { + strDownBuffer[bar_index] = strPriceBuffer[bar_index] - (strMultiplier * atr); + } + + // + // Draw the indicator ... + + // + double colorIDX = hideColorIDX; + strColorBuffer[bar_index] = colorIDX; + + // + if (strStateBuffer[bar_index] == 1) + { + // + strBuffer[bar_index] = strDownBuffer[bar_index]; + if (changeOfTrend == 1) + { + strBuffer[bar_index - 1] = strBuffer[bar_index - 2]; + changeOfTrend = 0; + } + + // + colorIDX = bullishColorIDX; + } + else if (strStateBuffer[bar_index] == -1) + { + // + strBuffer[bar_index] = strUpBuffer[bar_index]; + if (changeOfTrend == 1) + { + // + strBuffer[bar_index - 1] = strBuffer[bar_index - 2]; + changeOfTrend = 0; + } + + // + colorIDX = bearishColorIDX; + } + + // + if (showStr) + { + strColorBuffer[bar_index] = colorIDX; + } + + // + // Str Mid ... + + // + double iStrMid = strDownBuffer[bar_index] + ((strUpBuffer[bar_index] - strDownBuffer[bar_index]) / 2); + + // +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xtb.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xtb.mq5 new file mode 100644 index 0000000..f40cea9 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xtb.mq5 @@ -0,0 +1,2966 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 X3MA +// Description: X3MA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XTB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XTB" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +enum ENUM_XCAEA_TIGGER_TYPE +{ + XCA_TRIGGER_NONE, // None + XCA_TRIGGER_BULL, // TriggerBull + XCA_TRIGGER_BEAR, // TriggerBear +}; + +// +bool IsValid(ENUM_XCAEA_TIGGER_TYPE value) +{ + return value != XCA_TRIGGER_NONE; +} + +// +string ToString(ENUM_XCAEA_TIGGER_TYPE value) +{ + return EnumToString(value); +} + +// +ENUM_XCAEA_TIGGER_TYPE GetType(string type) +{ + // + ENUM_XCAEA_TIGGER_TYPE result = XCA_TRIGGER_NONE; + + // + bool isTriggerBull = type == ToString(XCA_TRIGGER_BULL); + bool isTriggerBear = type == ToString(XCA_TRIGGER_BEAR); + + // + if (isTriggerBull) + { + result = XCA_TRIGGER_BULL; + } + else if (isTriggerBear) + { + result = XCA_TRIGGER_BEAR; + } + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCAEA_TIGGER_TYPE value) +{ + return value == XCA_TRIGGER_BULL + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; +} + +// +struct XTriggerBlock +{ + // + // Props ... + XBoxZone ob; // Order Block + XBoxZone fvg; // Fair Value Gap + XOHCL swingBar; // Swing of Trigger + XBoxZone trigger; // Trigger Block + XBoxZone rLiquidity; // Reversal Liquidity + XBoxZone fLiquidity; // Following Liquidity + + // + XSignal signal; // Pepared Signal + + // + // Constructor ... + XTriggerBlock() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ob.Clean(); + fvg.Clean(); + signal.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = ob.IsValid() && + fvg.IsValid() && + trigger.IsValid(); + + // + return result; + } + + // + bool IsBullish() + { + return IsValid() && + ob.IsBullish(); + } + + // + bool IsBearish() + { + return IsValid() && + ob.IsBearish(); + } + + // + int ToIndex() + { + return trigger.ToIndex(); + } + + // + int FromIndex() + { + return trigger.FromIndex(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (IsValid()) + { + result = ob.dir; + } + + // + return result; + } + + // +}; + +// +// Inputs ... +input group "Market"; +input ENUM_X_PERIOD_METHOD trendPeriodMethod = X_PERIOD_AUTO; // How to Find Trend Period +input ENUM_TIMEFRAMES trendPeriod = NULL; // Trend Time Period +input ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +input ENUM_APPLIED_PRICE trendAppliedTo = PRICE_CLOSE; // Trend Applied To +input double sarStep = 0.02; // Sar Step +input double sarMax = 0.2; // Sar Maximum +input int adxLength = 14; // ADX Length +input double adxThreshold = 25.0; // ADX Threshold +input int rsiLength = 14; // RSI Length +input double rsiOBLevel = 70.0; // RSI OB Level +input double rsiOSLevel = 30.0; // RSI OS Level +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input int atrLength = 14; // ATR Length +input double atrMultiplier = 1.5; // ATR Band Multiplier +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +input ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_SMA; // ATR Signalling Method +input int barsSignalLength = 14; // Bars Signal Length +input ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +input int deltaSignalLength = 14; // Delta Signal Length +input ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +input int volumeSignalLength = 14; // Volume Signal Length +input ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method +input int hkSignalBarLength = 14; // Hiken Ashi Signal Length +input ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method + +// +// Validating ... +input group "Validating"; +input bool forceHasSwing = true; // Force Blocks to Have Swing +input bool forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity +input bool forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity +input bool validateGapSequence = false; // Validate Block's Gap Sequence +input bool validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + +// +// Filtering ... +input group "Filtering"; +input bool filterBasedOnSar = false; // Filter Based on Sar +input bool filterBasedOnRSI = false; // Filter Based on RSI +input bool filterBasedOnADX = false; // Filter Based on ADX +input bool filterBasedOnATR = false; // Filter Based on ATR +input bool filterBasedOnTrend = false; // Filter Based on Trend +input bool filterBasedOnDelta = false; // Filter Based on Delta +input bool filterBasedOnVolume = false; // Filter Based on Volume +input bool filterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool filterBasedOnTrendBars = false; // Filter Based on Trend Bars +input bool filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + +// +// Alert ... +input group "Alerts"; +input string alertPrefix = ""; // Alert Prefix +input bool _logAlerts = true; // Log Alerts +input bool _pushAlerts = false; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = true; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showHKBars = false; // Show Hiken Ashi Bars +input bool showATRBand = false; // Show ATR Band +input bool showTrendBars = false; // Show Trend Bars +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +// Draws ... +input bool drawZones = false; // Draw Detected Zones +input bool drawSignals = false; // Draw Zone's Signal + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int sarArrowCode = 159; // Sar Arrow Code +input int rrZoneLength = 7; // Draw Risk Reward Ratio till n Bars +input int maxSignalR2R = 4; // Max Allowed Signal R2R +input double slAtrMultiplier = 0; // Additional SL ATR Multiplier + +// +// Styling ... + +// +// Trigger Block ... +input int tbWidth = 1; // Trigger Block Width +input color tbBullishColor = clrAqua; // Trigger Block Bullish Color +input color tbBearishColor = clrMagenta; // Trigger Block Bearish Color +input ENUM_LINE_STYLE tbStyle = STYLE_DASHDOTDOT; // Trigger Block Style + +// +// OB ... +input int obWidth = 1; // OB Width +input color obBullishColor = clrLime; // OB Bullish Color +input color obBearishColor = clrRed; // OB Bearish Color +input ENUM_LINE_STYLE obStyle = STYLE_DOT; // OB Style + +// +// FVG ... +input int fvgWidth = 2; // FVG Width +input color fvgBullishColor = clrLime; // FVG Bullish Color +input color fvgBearishColor = clrRed; // FVG Bearish Color +input ENUM_LINE_STYLE fvgStyle = STYLE_SOLID; // FVG Style + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 36 +#property indicator_plots 7 + +// +// Plot Buffers ... + +// +// TREND ... + +// +#define trendBufferIndex 0 +#define trendBufferPlotIndex 0 +double trendBuffer[]; + +// +#define trendColorBufferIndex 1 +double trendColorBuffer[]; + +// +#property indicator_label1 "X121 Trend" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_DASH +#property indicator_width1 2 + +// +// SAR ... + +// +#define sarBufferIndex 2 +#define sarBufferPlotIndex 2 +double sarBuffer[]; + +// +#define sarColorBufferIndex 3 +double sarColorBuffer[]; + +// +#property indicator_label2 "X121 SAR" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_width2 2 + +// +// Signal Bar ... + +// +#define openSignalBufferIndex 4 +double openSignalBuffer[]; + +// +#define highSignalBufferIndex 5 +double highSignalBuffer[]; + +// +#define lowSignalBufferIndex 6 +double lowSignalBuffer[]; + +// +#define closeSignalBufferIndex 7 +double closeSignalBuffer[]; + +// +#define signalBarColorBufferIndex 8 +double signalBarColorBuffer[]; + +// +#define signalBarBufferIndex 2 +#property indicator_label3 "X121 XSGB Open;X121 XSGB High;X121 XSGB Low;X121 XSGB Close" +#property indicator_type3 DRAW_COLOR_CANDLES +#property indicator_color3 CLR_NONE, clrLime, clrRed + +// +// XHK ... + +// +#define openHKBufferIndex 9 +double openHKBuffer[]; + +// +#define highHKBufferIndex 10 +double highHKBuffer[]; + +// +#define lowHKBufferIndex 11 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex 12 +double closeHKBuffer[]; + +// +#define barHKColorBufferIndex 13 +double barHKColorBuffer[]; + +// +#define barHKBufferIndex 3 +#property indicator_label4 "X121 XHK Open;X121 XHK High;X121 XHK Low;X121 XHK Close" +#property indicator_type4 DRAW_COLOR_CANDLES +#property indicator_color4 CLR_NONE, clrDodgerBlue, clrDarkGoldenrod + +// +// XHK SIGNAL ... + +// +// Open ... +#define openHKSignalBufferIndex 14 +double openHKSignalBuffer[]; + +// +// High ... +#define highHKSignalBufferIndex 15 +double highHKSignalBuffer[]; + +// +// Low ... +#define lowHKSignalBufferIndex 16 +double lowHKSignalBuffer[]; + +// +// Close ... +#define closeHKSignalBufferIndex 17 +double closeHKSignalBuffer[]; + +// +// Candle Color ... +#define barHKSignalColorBufferIndex 18 +double barHKSignalColorBuffer[]; + +// +#define barHKSignalBufferIndex 4 +#property indicator_label5 "X121 XHKSM Open;X121 XHKSM High;X121 XHKSM Low;X121 XHKSM Close" +#property indicator_type5 DRAW_COLOR_CANDLES +#property indicator_color5 CLR_NONE, clrAqua, clrMagenta + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 19 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +#property indicator_label6 "X121 XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 20 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +#property indicator_label7 "X121 XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 20 + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 1 +double trendStateBuffer[]; + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 2 +double sarStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +XCAlert *alert; +double mPoints = 0; +CArrayObj mObjects; +XCPOIDrawer *drawer; +bool mEnableAlerts = false; +XCBarAnalyser *barAnalyser; +int mTrendPeriodLength = 0; +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; +ENUM_TIMEFRAMES mTrendPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // Configure Alert ... + alert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(alertPrefix) + ? "" + : "[" + alertPrefix + "]"); + alert.SetPrefix(mPrefix); + alert.SetLogAlerts(_logAlerts); + alert.SetMailAlerts(_mailAlerts); + alert.SetPushAlerts(_pushAlerts); + alert.SetEnableAlerts(mEnableAlerts); + alert.SetTerminalAlerts(_terminalAlerts); + + // + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + // Initializing TrendPeriod ... + int cPeriodSeconds = PeriodSeconds(_Period); + if (trendPeriodMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mTrendPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mTrendPeriod = trendPeriod; + } + if (IsValid(mTrendPeriod)) + { + mTrendPeriodLength = PeriodSeconds(mTrendPeriod) / cPeriodSeconds; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + bool isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = adxHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mTrendPeriodLength, + 0, + trendMode, + trendAppliedTo // + ); + isInited = trendHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + mPoints = GetPoints(_Symbol); + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + ReadBarStyle(); + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + mObjects.Clear(); + + // + delete alert; + delete drawer; + + // + ZeroMemory(alert); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + + // + ShowBars(); + + // + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + adxLength > 0 && + atrLength > 0 && + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + barsSignalLength > 2 && + deltaSignalLength > 2 && + hkSignalBarLength > 2 && + volumeSignalLength > 2 && + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + barsSignalMethod != X_MA_MODE_NONE && + deltaSignalMethod != X_MA_MODE_NONE && + hkSignalBarMethod != X_MA_MODE_NONE && + volumeSignalMethod != X_MA_MODE_NONE && + IsValid(trendPeriodMethod, trendPeriod) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(adxLength, rsiLength); + result = MathMax(result, barsSignalLength); + result = MathMax(result, deltaSignalLength); + result = MathMax(result, volumeSignalLength); + result = MathMax(result, hkSignalBarLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + + // + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + + // + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(signalBarColorBuffer, true); + SetIndexBuffer(signalBarColorBufferIndex, signalBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(signalBarBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(signalBarBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openSignalBuffer, true); + SetIndexBuffer(openSignalBufferIndex, openSignalBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highSignalBuffer, true); + SetIndexBuffer(highSignalBufferIndex, highSignalBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeSignalBuffer, true); + SetIndexBuffer(closeSignalBufferIndex, closeSignalBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowSignalBuffer, true); + SetIndexBuffer(lowSignalBufferIndex, lowSignalBuffer, INDICATOR_DATA); + + // + // XHK ... + + // + // HK Bars Color ... + ArraySetAsSeries(barHKColorBuffer, true); + SetIndexBuffer(barHKColorBufferIndex, barHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(barHKBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(barHKBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL ... + + // + // HK Bars Color ... + ArraySetAsSeries(barHKSignalColorBuffer, true); + SetIndexBuffer(barHKSignalColorBufferIndex, barHKSignalColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(barHKSignalBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(barHKSignalBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKSignalBuffer, true); + SetIndexBuffer(openHKSignalBufferIndex, openHKSignalBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKSignalBuffer, true); + SetIndexBuffer(highHKSignalBufferIndex, highHKSignalBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKSignalBuffer, true); + SetIndexBuffer(closeHKSignalBufferIndex, closeHKSignalBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKSignalBuffer, true); + SetIndexBuffer(lowHKSignalBufferIndex, lowHKSignalBuffer, INDICATOR_DATA); + + // + // ATR ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // Data Buffers ... + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int bar_index) +{ + // + sarColorBuffer[bar_index] = hideColorIDX; + trendColorBuffer[bar_index] = hideColorIDX; +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + // Bar Info ... + double iLow = high[bar_index]; + double iHigh = high[bar_index]; + double iClose = close[bar_index]; + double iOpen = open[bar_index]; + double iVolume = (double)iVolume(_Symbol, _Period, bar_index); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double points = GetPoints(_Symbol); + + // + // Calculate Sar Color Buffer ... + double iSar = sarBuffer[bar_index]; + + // + double iSarState = neuturalState; + double iSarColor = neuturalColorIDX; + if (iLow > iSar) + { + // + iSarState = bullishState; + iSarColor = !showSar + ? hideColorIDX + : bullishColorIDX; + } + else if (iHigh < iSar) + { + // + iSarState = bearishState; + iSarColor = !showSar + ? hideColorIDX + : bearishColorIDX; + } + sarStateBuffer[bar_index] = iSarState; + sarColorBuffer[bar_index] = iSarColor; + + // + // Calculate Trend Color Buffer ... + double iTrend = trendBuffer[bar_index]; + + // + double iTrendState = neuturalState; + double iTrendColor = neuturalColorIDX; + if (iClose > iTrend) + { + // + iTrendState = bullishState; + iTrendColor = !showTrend + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTrend) + { + // + iTrendState = bearishState; + iTrendColor = !showTrend + ? hideColorIDX + : bearishColorIDX; + } + trendStateBuffer[bar_index] = iTrendState; + trendColorBuffer[bar_index] = iTrendColor; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[bar_index] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + deltaSignalLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); + + // + // VOLUME ... + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[bar_index] = iBullishVolume; + bearishVolumeBuffer[bar_index] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + // SIGNAL Bar ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + barsSignalLength, + open, + openSignalBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + barsSignalLength, + close, + closeSignalBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(closeSignalBuffer[bar_index], openSignalBuffer[bar_index]); + double max = MathMin(closeSignalBuffer[bar_index], openSignalBuffer[bar_index]); + + // + lowSignalBuffer[bar_index] = min; + highSignalBuffer[bar_index] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + openSignalBuffer[bar_index] < closeSignalBuffer[bar_index] + ? bullishColorIDX + : bearishColorIDX; + signalBarColorBuffer[bar_index] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; + + // + // XHK ... + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double iHKHighValue = MathMax(high[bar_index], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[bar_index], MathMin(iHKOpenValue, iHKCloseValue)); + + // + double iHKColorValue = + iHKOpenValue < iHKCloseValue + ? bullishColorIDX + : bearishColorIDX; + + // + // Raw HK Buffers ... + openHKBuffer[bar_index] = iHKOpenValue; + highHKBuffer[bar_index] = iHKHighValue; + lowHKBuffer[bar_index] = iHKLowValue; + closeHKBuffer[bar_index] = iHKCloseValue; + barHKColorBuffer[bar_index] = showHKBars ? iHKColorValue + : hideColorIDX; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + hkSignalBarLength, + openHKBuffer, + openHKSignalBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + hkSignalBarLength, + closeHKBuffer, + closeHKSignalBuffer, + hkSignalBarMethod // + ); + + // + min = MathMin(closeHKSignalBuffer[bar_index], openHKSignalBuffer[bar_index]); + max = MathMin(closeHKSignalBuffer[bar_index], openHKSignalBuffer[bar_index]); + + // + lowHKSignalBuffer[bar_index] = min; + highHKSignalBuffer[bar_index] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + openHKSignalBuffer[bar_index] < closeHKSignalBuffer[bar_index] + ? bullishColorIDX + : bearishColorIDX; + barHKSignalColorBuffer[bar_index] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; + + // + // Calculate ATR Band ... + double iATR = atrBuffer[bar_index]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + bar_index // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + bar_index // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[bar_index] = iATRUpper; + atrLowerRawBuffer[bar_index] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[bar_index] = iATRUpper; + atrLowerBuffer[bar_index] = iATRLower; + } + + // + // Trigger Block ... + + // + DetectTriggerBlock( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +/** + * Detect Trigger Block ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DetectTriggerBlock( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = bar_index + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + bar_index == maxBarIndex; + + // + // Prevent Calculation ... + if (maxBarIndex - bar_index < maxLength) + { + return; + } + + // + int zIDX = 0; + bool has = false; + bool isDone = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Retrieve Required Bars ... + + // + XOHCL iBar; + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + has = zBar.Init( + _Symbol, + _Period, + bar_index // + ); + + // + // Detect Trend Bar ... + XOHCL zTrendBar; + int zTrendIDX = iBarShift( + _Symbol, + mTrendPeriod, + zBar.time // + ); + has = + has && + zTrendBar.Init( + _Symbol, + mTrendPeriod, + zTrendIDX + 1 // + ); + + // + // Define Zone Structure ... + XTriggerBlock tb; + + // + bool validateObBarType = true; + bool validateFVGBarType = true; + + // + // Detect Based Order Block ... + has = + has && + barAnalyser.IsOB( + zBar, + tb.ob, + validateFVGBarType, // Force FVG Bar Type ... + validateObBarType // Force Block Two Bar Checking ... + ); + + // + // Detect Based Fair Value Gap ... + has = + has && + barAnalyser.IsFVG( + zBar, + tb.fvg, + validateFVGBarType // Force FVG Bar Type ... + ); + + // + // Clone Trigger Block ... + if (has) + { + tb.trigger = tb.ob; + } + + // + bool isBullish = + has && + tb.IsBullish(); + + // + bool isBearish = + has && + tb.IsBearish(); + + // + int toIDX = tb.ToIndex(); + int fromIDX = tb.FromIndex(); + + // + // Verifications and Filters ... + + // + int loopback = 144; + + // + // Forces ... + + // + // Force Has Proper Swing ... + if (has && + forceHasSwing) + { + // + toIDX = tb.ToIndex(); + fromIDX = tb.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize iBar ... + isDone = iBar.Init( + zBar.symbol, + zBar.period, + i // + ); + isDone = + isDone && + barAnalyser.IsSimpleSwing( + iBar, + iDir // + ) && + iDir == tb.GetDirection(); + if (isDone) + { + // + bool canSet = + !tb.swingBar.IsValid() + ? true + : (isBullish + ? tb.swingBar.low > iBar.low + : tb.swingBar.high < iBar.high); + if (canSet) + { + tb.swingBar = iBar; + } + } + + // + iBar.Clean(); + } + + // + has = tb.swingBar.IsValid(); + } + + // + // Force Has Liquidity ... + if (has && + (forceHasFLiquidity || + forceHasRLiquidity)) + { + // + toIDX = tb.ToIndex(); + fromIDX = tb.FromIndex(); + for (int i = toIDX; i < fromIDX + loopback; i++) + { + // + // Initialize iBar ... + isDone = iBar.Init( + zBar.symbol, + zBar.period, + i // + ); + + // + bool isRejected = + isDone && + barAnalyser.IsRejected( + iBar, + iDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + + // + // Following Liquidity ... + bool isFLiq = + isDone && + isRejected && + iDir == tb.GetDirection() && + (isBullish + ? iBar.low < tb.trigger.lower + : iBar.high > tb.trigger.upper); + if (isFLiq && + forceHasFLiquidity && + !tb.fLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iDir, + tb.fLiquidity, + tb.trigger.to // + ); + } + + // + // Reversal Liquidity ... + bool isRLiq = + isDone && + isRejected && + Opposit(iDir) == tb.GetDirection() && + (isBullish + ? iBar.low > tb.trigger.upper + : iBar.high < tb.trigger.lower); + if (isRLiq && + forceHasRLiquidity && + !tb.rLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iDir, + tb.rLiquidity, + tb.trigger.to // + ); + } + + // + // Checking Conditions ... + isDone = + (!forceHasFLiquidity + ? true + : tb.fLiquidity.IsValid()) && + (!forceHasRLiquidity + ? true + : tb.rLiquidity.IsValid()); + if (isDone) + { + // + iBar.Clean(); + break; + } + + // + iBar.Clean(); + } + + // + // Checking Conditions ... + has = + (!forceHasFLiquidity + ? true + : tb.fLiquidity.IsValid()) && + (!forceHasRLiquidity + ? true + : tb.rLiquidity.IsValid()); + } + + // + // Validations ... + + // + // Validating Gap Sequence means + // Gap Bars must Follow each Other ... + if (has && + validateGapSequence) + { + // + XOHCL iPBar; + toIDX = tb.fvg.ToIndex(); + fromIDX = tb.fvg.FromIndex(); + + // + for (int i = toIDX; i < fromIDX - 1; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + zBar.symbol, + zBar.period, + i // + ); + has = + has && + iBar.GetPreviousBar(iPBar); + has = + has && + (isBullish + ? iBar.low > iPBar.low + : iBar.high < iPBar.high); + if (!has) + { + break; + } + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + // Validate Block Edge Breakout ... + if (has && + validateBlockEdgeBreakout) + { + // + has = tb.fvg.ToBar(iBar); + has = + has && + (isBullish + ? (iBar.GetDown() < tb.ob.upper && + iBar.GetUp() > tb.ob.upper) + : (iBar.GetDown() < tb.ob.lower && + iBar.GetUp() > tb.ob.lower)); + + // + iBar.Clean(); + } + + // + // Filters ... + + // + // DELTA ... + if (has && + filterBasedOnDelta) + { + // + double iDelta = deltaBuffer[bar_index]; + double iPDelta = deltaBuffer[lastBarIndex]; + + // + bool isDeltaUp = iDelta > iPDelta; + bool isDeltaDown = iDelta < iPDelta; + + // + double iDeltaSignal = deltaSignalBuffer[bar_index]; + double iPDeltaSignal = deltaSignalBuffer[lastBarIndex]; + + // + bool isDeltaSignalUp = iDeltaSignal > iPDeltaSignal; + bool isDeltaSignalDown = iDeltaSignal < iPDeltaSignal; + + // + bool isDeltaSwitchedToBullish = + isDeltaUp && + isDeltaSignalUp && + iDelta > iDeltaSignal && + iPDelta < iPDeltaSignal; + + // + bool isDeltaSwitchedToBearish = + isDeltaDown && + isDeltaSignalDown && + iDelta < iDeltaSignal && + iPDelta > iPDeltaSignal; + + // + has = + has && + (isBullish + ? isDeltaSwitchedToBullish + : isDeltaSwitchedToBearish); + } + + // + // VOLUME ... + if (has && + filterBasedOnVolume) + { + // + double iBullishVolumeSignal = bullishVolumeSignalBuffer[bar_index]; + double iPBullishVolumeSignal = bullishVolumeSignalBuffer[lastBarIndex]; + + // + bool isBullishVolumeSignalUp = iBullishVolumeSignal > iPBullishVolumeSignal; + bool isBullishVolumeSignalDown = iBullishVolumeSignal < iPBullishVolumeSignal; + + // + double iBearishVolumeSignal = bearishVolumeSignalBuffer[bar_index]; + double iPBearishVolumeSignal = bearishVolumeSignalBuffer[lastBarIndex]; + + // + bool isBearishVolumeSignalUp = iBearishVolumeSignal > iPBearishVolumeSignal; + bool isBearishVolumeSignalDown = iBearishVolumeSignal < iPBearishVolumeSignal; + + // + bool isVolumeSwitchdToBullish = + isBullishVolumeSignalUp && + !isBearishVolumeSignalUp && + iBullishVolumeSignal > iBearishVolumeSignal && + iPBullishVolumeSignal < iPBearishVolumeSignal; + + // + bool isVolumeSwitchdToBearish = + isBearishVolumeSignalUp && + !isBullishVolumeSignalUp && + iBearishVolumeSignal > iBullishVolumeSignal && + iPBearishVolumeSignal < iPBullishVolumeSignal; + + // + has = + has && + (isBullish + ? isVolumeSwitchdToBullish + : isVolumeSwitchdToBearish); + } + + // + // SIGNAL Bar ... + if (has && + filterBasedOnSignalBar) + { + // + double iSignalOpen = openSignalBuffer[bar_index]; + double iPSignalOpen = openSignalBuffer[lastBarIndex]; + + // + double iSignalClose = closeSignalBuffer[bar_index]; + double iPSignalClose = closeSignalBuffer[lastBarIndex]; + + // + bool isSignalBarBullish = iSignalOpen < iSignalClose; + bool isPSignalBarBullish = iPSignalOpen < iPSignalClose; + + // + bool isSignalBarBearish = iSignalOpen > iSignalClose; + bool isPSignalBarBearish = iPSignalOpen > iPSignalClose; + + // + bool isSignalBarSwitchedToBullish = + isSignalBarBullish && + !isPSignalBarBullish; + + // + bool isSignalBarSwitchedToBearish = + isSignalBarBearish && + !isPSignalBarBearish; + + // + has = + has && + (isBullish + ? isSignalBarSwitchedToBullish + : isSignalBarSwitchedToBearish); + } + + // + // HK SIGNAL Bar ... + if (has && + filterBasedOnHKSignalBar) + { + // + double iHKSignalOpen = openHKSignalBuffer[bar_index]; + double iPHKSignalOpen = openHKSignalBuffer[lastBarIndex]; + + // + double iHKSignalClose = closeHKSignalBuffer[bar_index]; + double iPHKSignalClose = closeHKSignalBuffer[lastBarIndex]; + + // + bool isHKSignalBarBullish = iHKSignalOpen < iHKSignalClose; + bool isPHKSignalBarBullish = iPHKSignalOpen < iPHKSignalClose; + + // + bool isHKSignalBarBearish = iHKSignalOpen > iHKSignalClose; + bool isPHKSignalBarBearish = iPHKSignalOpen > iPHKSignalClose; + + // + bool isHKSignalBarSwitchedToBullish = + isHKSignalBarBullish && + !isPHKSignalBarBullish; + + // + bool isHKSignalBarSwitchedToBearish = + isHKSignalBarBearish && + !isPHKSignalBarBearish; + + // + has = + has && + (isBullish + ? isHKSignalBarSwitchedToBullish + : isHKSignalBarSwitchedToBearish); + } + + // + // ATR ... + if (has && + filterBasedOnATR) + { + // + fromIDX = tb.FromIndex(); + double iATRUpper = atrUpperBuffer[fromIDX]; + double iATRLower = atrLowerBuffer[fromIDX]; + + // + has = + has && + (isBullish + ? tb.trigger.lower < iATRLower + : tb.trigger.upper > iATRUpper); + } + + // + // SAR ... + if (has && + filterBasedOnSar) + { + // + double iSarState = sarStateBuffer[bar_index]; + double iPSarState = sarStateBuffer[lastBarIndex]; + double iP2SarState = sarStateBuffer[lastBarIndex + 1]; + + // + bool isSarBullish = iSarState > 0; + bool isPSarBullish = iPSarState > 0; + bool isP2SarBullish = iP2SarState > 0; + + // + bool isSarBearish = iSarState < 0; + bool isPSarBearish = iPSarState < 0; + bool isP2SarBearish = iP2SarState < 0; + + // + bool isSarSwitchedToBullish = + isSarBullish && + !isPSarBullish; + + // + bool isSarSwitchedToBearish = + isSarBearish && + !isPSarBearish; + + // + bool isSarPSwitchedToBullish = + isPSarBullish && + !isP2SarBullish; + + // + bool isSarPSwitchedToBearish = + isPSarBearish && + !isP2SarBearish; + + // + has = + has && + (isBullish + ? (isSarSwitchedToBullish || + isSarPSwitchedToBullish) + : (isSarSwitchedToBearish || + isSarPSwitchedToBearish)); + } + + // + // TREND ... + if (has && + filterBasedOnTrend) + { + // + double iTrendState = trendStateBuffer[bar_index]; + double iPTrendState = trendStateBuffer[lastBarIndex]; + + // + bool isTrendBullish = iTrendState > 0; + bool isPTrendBullish = iPTrendState > 0; + + // + bool isTrendBearish = iTrendState < 0; + bool isPTrendBearish = iPTrendState < 0; + + // + double trends[]; + int toIDX = tb.ToIndex(); + int fromIDX = tb.FromIndex(); + double iTrend = trendBuffer[toIDX]; + for (int i = toIDX; i <= fromIDX; i++) + { + // + Add( + trendBuffer[i], + trends // + ); + } + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + bool isTrendUp = + iTrend > trendsMin && + iTrend >= trendsAVG; + + // + bool isTrendDown = + iTrend < trendsMax && + iTrend <= trendsAVG; + + // + bool isTrendSwitchedToBullish = + isTrendUp && + isTrendBullish && + !isPTrendBullish; + + // + bool isTrendSwitchedToBearish = + isTrendDown && + isTrendBearish && + !isPTrendBearish; + + // + has = + has && + (isBullish + ? isTrendSwitchedToBullish + : isTrendSwitchedToBearish); + } + + // + // TREND Bars ... + if (has && + zTrendBar.IsValid() && + filterBasedOnTrendBars) + { + // + // Calculate Trend Bar's Midd Range ... + double mid = zTrendBar.low + ((zTrendBar.high - zTrendBar.low) / 2); + + // + // Check zBar Close based on MID ... + has = + has && + (isBullish + ? zBar.close < mid + : zBar.close > mid); + + // + // Check Trigger Block ... + has = + has && + (isBullish + ? tb.trigger.lower < zTrendBar.GetDown() + : tb.trigger.upper > zTrendBar.GetUp()); + } + + // + // RSI ... + if (has && + filterBasedOnRSI) + { + // + double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2; + + // + double iRSI = rsiBuffer[bar_index]; + double iPRSI = rsiBuffer[lastBarIndex]; + double iP2RSI = rsiBuffer[lastBarIndex + 1]; + + // + bool isRSICrossedOverOS = + iRSI > rsiOSLevel && + iPRSI <= rsiOSLevel; + + // + bool isRSICrossedUnderOB = + iRSI < rsiOBLevel && + iPRSI >= rsiOBLevel; + + // + bool isPRSICrossedOverOS = + iPRSI > rsiOSLevel && + iP2RSI <= rsiOSLevel; + + // + bool isPRSICrossedUnderOB = + iPRSI < rsiOBLevel && + iP2RSI >= rsiOBLevel; + + // + has = + has && + (isBullish + ? (isRSICrossedOverOS || + isPRSICrossedOverOS) + : (isRSICrossedUnderOB || + isPRSICrossedUnderOB)); + } + + // + // ADX ... + if (has && + filterBasedOnADX) + { + // + // ADX ... + double iADX = adxBuffer[bar_index]; + double iPADX = adxBuffer[lastBarIndex]; + double iP2ADX = adxBuffer[lastBarIndex + 1]; + + // + // ADX +DI ... + double iADXP = adxpBuffer[bar_index]; + double iPADXP = adxpBuffer[lastBarIndex]; + double iP2ADXP = adxpBuffer[lastBarIndex + 1]; + + // + // ADX -DI ... + double iADXN = adxnBuffer[bar_index]; + double iPADXN = adxnBuffer[lastBarIndex]; + double iP2ADXN = adxnBuffer[lastBarIndex + 1]; + + // + // Preparing Conditions ... + + // + bool isADXBullish = iADX > adxThreshold; + bool isADXBearish = iADX < adxThreshold; + + // + bool isPADXBullish = iPADX > adxThreshold; + bool isPADXBearish = iPADX < adxThreshold; + + // + bool isP2ADXBullish = iP2ADX > adxThreshold; + bool isP2ADXBearish = iP2ADX < adxThreshold; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + + // + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isPADXBearish && + !isP2ADXBearish; + + // + has = + has && + (isBullish + ? (isADXSwitchedToBullish || + isPADXSwitchedToBullish) + : (isADXSwitchedToBearish || + isPADXSwitchedToBearish)); + } + + // + // SIGNAL ... + if (has && + (drawSignals && + maxSignalR2R > 0)) + { + // + double targets[]; + for (int i = 1; i <= maxSignalR2R; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + double iATR = atrBuffer[bar_index]; + double slAdditional = slAtrMultiplier * iATR; + + // + has = ToSignal( + tb.trigger, + tb.signal, + targets, + slAdditional // + ); + } + + // + // Handle Draw ... + + // + // Draw Trend Bar ... + if (has && + showTrendBars) + { + // + XCOHCLObject *iObj; + isDone = drawer.CreateBar( + zTrendBar, + iObj, + zBar.time // + ); + if (isDone) + { + // + // Style Object ... + + // + // Store Object ... + mObjects.Add(iObj); + } + } + + // + // Draw Trigger Block ... + if (has && + drawZones) + { + DrawTB(tb); + } + + // + // Handle Alerst ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (has && + (canAlert || + canLogOnly)) + { + // + string message = + tb.trigger.symbol + "," + + ToString(tb.trigger.period) + "> " + + ToString(tb.trigger.dir) + + " Zone Detected at: " + ToString(tb.trigger.to); + + // + if (canLogOnly) + { + alert.LogAlert(message); + } + else if (canAlert) + { + alert.SendAlert(message); + } + } + + // + // Cleanup Resources ... + + // + tb.Clean(); + zBar.Clean(); + iBar.Clean(); + zTrendBar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// +// Draw Specific Trigger Block ... +bool DrawTB( + XTriggerBlock &trigger, + datetime to = NULL // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = trigger.IsValid(); + if (!result) + { + return result; + } + + // + // Update To ... + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + // + trigger.trigger.to = to; + trigger.rLiquidity.to = to; + trigger.fLiquidity.to = to; + } + + // + bool isBullish = trigger.IsBullish(); + + // + // Draw OB ... + if (trigger.ob.IsValid()) + { + // + XCBoxObject *iOBObj; + result = drawer.DrawBox( + trigger.ob, + iOBObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? obBullishColor + : obBearishColor; + + // + iOBObj.BoxColor(iClr); + iOBObj.BoxWidth(obWidth); + iOBObj.BoxStyle(obStyle); + + // + // Store Object ... + mObjects.Add(iOBObj); + } + ZeroMemory(iOBObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw FVG ... + if (trigger.fvg.IsValid()) + { + // + XCBoxObject *iFVGObj; + result = drawer.DrawBox( + trigger.fvg, + iFVGObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? fvgBullishColor + : fvgBearishColor; + + // + iFVGObj.BoxColor(iClr); + iFVGObj.BoxWidth(fvgWidth); + iFVGObj.BoxStyle(fvgStyle); + + // + // Store Object ... + mObjects.Add(iFVGObj); + } + ZeroMemory(iFVGObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Trigger ... + if (trigger.trigger.IsValid()) + { + // + XCBoxObject *iTriggerObj; + result = drawer.DrawBox( + trigger.trigger, + iTriggerObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? tbBullishColor + : tbBearishColor; + + // + iTriggerObj.BoxColor(iClr); + iTriggerObj.BoxWidth(tbWidth); + iTriggerObj.BoxStyle(tbStyle); + + // + // Store Object ... + mObjects.Add(iTriggerObj); + } + ZeroMemory(iTriggerObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Liquidities ... + + // + // Reversla Liquidity ... + if (trigger.rLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + trigger.rLiquidity, + iLiqObj // + ); + if (result) + { + mObjects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Following Liquidity ... + if (trigger.fLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + trigger.fLiquidity, + iLiqObj // + ); + if (result) + { + mObjects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Swing Bar ... + if (trigger.swingBar.IsValid()) + { + // + color swingColor = + trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + ENUM_X_PRICE swingPType = + trigger.fvg.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *swingObj; + result = drawer.CreateBarArrow( + trigger.swingBar, + swingObj, + swingPType, + 159, + swingColor // + ); + if (result) + { + mObjects.Add(swingObj); + } + ZeroMemory(swingObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw RR of Signal ... + if (trigger.signal.IsValid() && + rrZoneLength > 0) + { + // + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + result = iRRObj.Create( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + trigger.signal, + rrZoneLength // + ); + if (result) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + mObjects.Add(iRRObj); + } + ZeroMemory(iRRObj); + + // + if (result) + { + return result; + } + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xvolume.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xvolume.mq5 new file mode 100644 index 0000000..657cb9a --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xvolume.mq5 @@ -0,0 +1,567 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Ocillator +// ------------------------------------------------- +// Name: X121 XVolume +// Description: Detect Bullish/Bearish Volumes ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XVolume Ocillator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XVOLUME" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Makret ... +input group "Market"; +input int maLength = 14; // Moving Averge Length +input ENUM_X_MA_METHOD maMethod = X_MA_MODE_EMA; // Moving Averge Method + +// +// Presentation ... +input group "Presentation"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool showBullishVolume = true; // Show Bullish Volume +input bool showBullishVolumeMa = true; // Show Bullish Volume Moving Average +input bool showBearishVolume = true; // Show Bearish Volume +input bool showBearishVolumeMa = true; // Show Bearish Volume Moving Average + +// +// Buffers Props ... + +// +#property indicator_separate_window + +// +#property indicator_buffers 6 +#property indicator_plots 4 + +// +// Buffers ... + +// +#define bullishVolumeBufferIndex 0 +double bullishVolumeBuffer[]; + +#property indicator_label1 "Bullish Volume" +#property indicator_type1 DRAW_HISTOGRAM +#property indicator_color1 clrLime +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +#define bullishVolumeMaBufferIndex 1 +double bullishVolumeMaBuffer[]; + +#property indicator_label2 "Bullish Volume MA" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrLime +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define bearishVolumeBufferIndex 2 +double bearishVolumeBuffer[]; + +#property indicator_label3 "Bearish Volume" +#property indicator_type3 DRAW_HISTOGRAM +#property indicator_color3 clrRed +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define bearishVolumeMaBufferIndex 3 +double bearishVolumeMaBuffer[]; + +#property indicator_label4 "Bearish Volume MA" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrRed +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 3 + +// +#define rawBullishVolumeBufferIndex mLastBufferIndex + 1 +double rawBullishVolumeBuffer[]; + +// +#define rawBearishVolumeBufferIndex mLastBufferIndex + 2 +double rawBearishVolumeBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = maLength > 0 && + IsValid(maMethod); + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, maLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Bullish ... + + // + // Volume ... + ENUM_DRAW_TYPE bullishVolumeDrawType = showBullishVolume ? DRAW_HISTOGRAM : DRAW_NONE; + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bullishVolumeBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(bullishVolumeBufferIndex, PLOT_SHOW_DATA, showBullishVolume); + PlotIndexSetInteger(bullishVolumeBufferIndex, PLOT_DRAW_TYPE, bullishVolumeDrawType); + + // + // Average ... + ENUM_DRAW_TYPE bullishVolumeMaDrawType = showBullishVolumeMa ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(bullishVolumeMaBuffer, true); + SetIndexBuffer(bullishVolumeMaBufferIndex, bullishVolumeMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bullishVolumeMaBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(bullishVolumeMaBufferIndex, PLOT_SHOW_DATA, showBullishVolumeMa); + PlotIndexSetInteger(bullishVolumeMaBufferIndex, PLOT_DRAW_TYPE, bullishVolumeMaDrawType); + + // + // Bearish ... + + // + // Volume ... + ENUM_DRAW_TYPE bearishVolumeDrawType = showBearishVolume ? DRAW_HISTOGRAM : DRAW_NONE; + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bearishVolumeBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(bearishVolumeBufferIndex, PLOT_SHOW_DATA, showBearishVolume); + PlotIndexSetInteger(bearishVolumeBufferIndex, PLOT_DRAW_TYPE, bearishVolumeDrawType); + + // + // Average ... + ENUM_DRAW_TYPE bearishVolumeMaDrawType = showBearishVolumeMa ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(bearishVolumeMaBuffer, true); + SetIndexBuffer(bearishVolumeMaBufferIndex, bearishVolumeMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bearishVolumeMaBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(bearishVolumeMaBufferIndex, PLOT_SHOW_DATA, showBearishVolumeMa); + PlotIndexSetInteger(bearishVolumeMaBufferIndex, PLOT_DRAW_TYPE, bearishVolumeMaDrawType); + + // + // Data Buffers ... + + // + ArraySetAsSeries(rawBullishVolumeBuffer, true); + SetIndexBuffer(rawBullishVolumeBufferIndex, rawBullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rawBearishVolumeBuffer, true); + SetIndexBuffer(rawBearishVolumeBufferIndex, rawBearishVolumeBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + bullishVolumeBuffer[barIndex] = EMPTY_VALUE; + bullishVolumeMaBuffer[barIndex] = EMPTY_VALUE; + rawBullishVolumeBuffer[barIndex] = 0; + + // + bearishVolumeBuffer[barIndex] = EMPTY_VALUE; + bearishVolumeMaBuffer[barIndex] = EMPTY_VALUE; + rawBearishVolumeBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + XOHCL bar; + bool has = bar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!has) + { + return; + } + + // + double iBullishVolume = 0; + double iBearishVolume = 0; + + // + if (bar.IsBullish()) + { + // + iBullishVolume = (double)bar.volume; + iBearishVolume = 0; + } + else if (bar.IsBearish()) + { + // + iBearishVolume = (double)bar.volume; + iBullishVolume = 0; + } + else + { + // + double volume = ((double)bar.volume) / 2.0; + iBullishVolume = volume; + iBearishVolume = volume; + } + + // + bullishVolumeBuffer[bar_index] = + iBullishVolume == 0 + ? EMPTY_VALUE + : iBullishVolume; + rawBullishVolumeBuffer[bar_index] = iBullishVolume; + + // + bearishVolumeBuffer[bar_index] = + iBearishVolume == 0 + ? EMPTY_VALUE + : iBearishVolume; + rawBearishVolumeBuffer[bar_index] = iBearishVolume; + + // + // Calculate Moving Averages ... + + // + int bullishMAsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + maLength, + rawBullishVolumeBuffer, + bullishVolumeMaBuffer, + maMethod // + ); + + // + int bearishMAsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + maLength, + rawBearishVolumeBuffer, + bearishVolumeMaBuffer, + maMethod // + ); + + // + bar.Clean(); +} + +// diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xvwap.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xvwap.mq5 new file mode 100644 index 0000000..ca2a2c4 --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xvwap.mq5 @@ -0,0 +1,712 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XVWAP +// Description: XVWAP ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XVWAP Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XVWAP" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int vwapFastLength = 20; // Fast Length +input int vwapMidLength = 40; // Mid Length +input int vwapSlowLength = 60; // Slow Length +input ENUM_APPLIED_PRICE vwapAppliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showVWapFast = true; // Show VWap Fast +input bool showVWapMedium = true; // Show VWap Medium +input bool showVWapSlow = true; // Show VWap Slow + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 11 +#property indicator_plots 3 + +// +// Plot Buffers ... + +// +// FAST ... +#define vwapFastBufferIndex 0 +double vwapFastBuffer[]; + +#define vwapFastColorBufferIndex 1 +double vwapFastColorBuffer[]; + +// +#define vwapFastPlotBufferIndex 0 +#property indicator_label1 "X121 VWF" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// MID ... +#define vwapMidBufferIndex 2 +double vwapMidBuffer[]; + +#define vwapMidColorBufferIndex 3 +double vwapMidColorBuffer[]; + +// +#define vwapMidPlotBufferIndex 1 +#property indicator_label2 "X121 VWM" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +// SLOW ... +#define vwapSlowBufferIndex 4 +double vwapSlowBuffer[]; + +#define vwapSlowColorBufferIndex 5 +double vwapSlowColorBuffer[]; + +// +#define vwapSlowPlotBufferIndex 2 +#property indicator_label3 "X121 VWS" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 5; + +// +// Volume ... +#define vwapVolumeBufferIndex mLastBufferIndex + 1 +double vwapVolumeBuffer[]; + +// +// Price ... +#define vwapPriceBufferIndex mLastBufferIndex + 2 +double vwapPriceBuffer[]; + +// +// Fast State ... +#define vwapFastStateBufferIndex mLastBufferIndex + 3 +double vwapFastStateBuffer[]; + +// +// Mid State ... +#define vwapMidStateBufferIndex mLastBufferIndex + 4 +double vwapMidStateBuffer[]; + +// +// Slow State ... +#define vwapSlowStateBufferIndex mLastBufferIndex + 5 +double vwapSlowStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Fast ... + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapFastColorBuffer, true); + SetIndexBuffer(vwapFastBufferIndex, vwapFastBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapFastColorBufferIndex, vwapFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapMidColorBuffer, true); + SetIndexBuffer(vwapMidBufferIndex, vwapMidBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapMidColorBufferIndex, vwapMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapSlowColorBuffer, true); + SetIndexBuffer(vwapSlowBufferIndex, vwapSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapSlowColorBufferIndex, vwapSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // Volumes ... + ArraySetAsSeries(vwapVolumeBuffer, true); + SetIndexBuffer(vwapVolumeBufferIndex, vwapVolumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(vwapPriceBuffer, true); + SetIndexBuffer(vwapPriceBufferIndex, vwapPriceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(vwapFastStateBuffer, true); + SetIndexBuffer(vwapFastStateBufferIndex, vwapFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(vwapMidStateBuffer, true); + SetIndexBuffer(vwapMidStateBufferIndex, vwapMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(vwapSlowStateBuffer, true); + SetIndexBuffer(vwapSlowStateBufferIndex, vwapSlowStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Required VWAP Data Buffers ... + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Prevent Moving Forward ... + } + else + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + vwapFastBuffer[barIndex] = EMPTY_VALUE; + vwapMidBuffer[barIndex] = EMPTY_VALUE; + vwapSlowBuffer[barIndex] = EMPTY_VALUE; + vwapVolumeBuffer[barIndex] = EMPTY_VALUE; + vwapPriceBuffer[barIndex] = EMPTY_VALUE; + + // + vwapFastColorBuffer[barIndex] = hideColorIDX; + vwapMidColorBuffer[barIndex] = hideColorIDX; + vwapSlowColorBuffer[barIndex] = hideColorIDX; + vwapFastStateBuffer[barIndex] = hideColorIDX; + vwapMidStateBuffer[barIndex] = hideColorIDX; + vwapSlowStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate VWAP Value for Specified Bar ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Specified VWAP Length ... + * @param _show: Boolean, Specified Show Buffer or not ... + * @param _buffer: Double Array Reference, Points to Buffer ... + * @param _colorBuffer: Double Array Reference, Points to Color Buffer ... + * @param _stateBuffer: Double Array Reference, Points to State Buffer ... + */ +void CalculateVWAP( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += vwapPriceBuffer[x + bar_index]; + vSum += vwapVolumeBuffer[x + bar_index]; + mSum += vwapPriceBuffer[x + bar_index] * vwapVolumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (_show) + { + _colorBuffer[bar_index] = iColor; + } +} + +/** + * Calculate VWAP Required Data Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPDataBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + ENUM_X_PRICE mPType = ToXPrice(vwapAppliedTo); + double price = GetAppliedPrice( + mPType, + open, + high, + low, + close, + bar_index // + ); + vwapPriceBuffer[bar_index] = price; + vwapVolumeBuffer[bar_index] = (double)tickVolume[bar_index]; +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPS( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapFastLength, + showVWapFast, + vwapFastBuffer, + vwapFastColorBuffer, + vwapFastStateBuffer // + ); + + // + // Mid ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapMidLength, + showVWapMedium, + vwapMidBuffer, + vwapMidColorBuffer, + vwapMidStateBuffer // + ); + + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapSlowLength, + showVWapSlow, + vwapSlowBuffer, + vwapSlowColorBuffer, + vwapSlowStateBuffer // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xwz.mq5 b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xwz.mq5 new file mode 100644 index 0000000..626ee8e --- /dev/null +++ b/BKPS/14040626/Documents/Indicators/x-saherelm.x121.xwz.mq5 @@ -0,0 +1,2780 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Glzoneal Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XWZ" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Detect Price Type + +// +input group "MA Detection"; +input int maLength = 20; // MA Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method + +// +input group "ATR StopLoss"; +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier + +// +input group "ADX Detection"; +input int adxLength = 14; // ADX Length +input double adxThreshold = 25; // ADX Threshold for Strong Trends + +// +input group "POI Detection"; +input ENUM_TIMEFRAMES orderBlockTF = PERIOD_H1; // Order Block Detection Time Frame +input ENUM_TIMEFRAMES fairValueGapTF = PERIOD_M15; // Fair Value Gap Detection Time Frame +input ENUM_TIMEFRAMES supDemTF = PERIOD_H4; // Supply and Demand Detection Time Frame + +// +input group "Alert"; +input bool mXWZEnableAlerts = true; // Enable Alerts +input bool mXWZPushAlerts = false; // Push Alerts +input bool mXWZMailAlerts = false; // Mail Alerts +input bool mXWZTerminalAlerts = false; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; + +// +input group "Buffer Presentation"; +input bool showMA = true; // Show Moving Average +input bool showPin = true; // Show Pin Bars +input bool showSwing = true; // Show Swing Bars +input bool showTrend = true; // Show Trend +input bool showEngulf = true; // Show Engulf Bars +input bool showLongSL = true; // Show Long SL +input bool showShortSL = true; // Show Short SL +input bool showMomentum = true; // Show Momentum Bars +input bool showRejection = true; // Show Rejection Bars + +// +input group "POI Presentation"; +input bool showPOIs = true; // Show POI(s) +input bool showOrderBlocks = true; // Show Order Blocks +input bool showFairValueGaps = true; // Show Fair Value Gaps +input bool showSupplyZones = true; // Show Supply Zones +input bool showDemandZones = true; // Show Demand Zones + +// +input group "Presentation Config"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int upTrendArrowCode = 236; // Up Trend Arrow Code +input int downTrendArrowCode = 238; // Down Trend Arrow Code +input int swingLowArrowCode = 108; // Swing Low Arrow Code +input int swingHighArrowCode = 108; // Swing High Arrow Code +input int bullishPinArrowCode = 246; // Bullish Pin Arrow Code +input int bearishPinArrowCode = 248; // Bearish Pin Arrow Code +input int bullishEngulfArrowCode = 200; // Bullish Engulf Arrow Code +input int bearishEngulfArrowCode = 202; // Bearish Engulf Arrow Code +input int bullishMomentumArrowCode = 233; // Bullish Momentum Arrow Code +input int bearishMomentumArrowCode = 234; // Bearish Momentum Arrow Code +input int bullishRejectionArrowCode = 241; // Bullish Rejection Arrow Code +input int bearishRejectionArrowCode = 242; // Bearish Rejection Arrow Code + +// +#property indicator_chart_window + +// +#property indicator_buffers 17 +#property indicator_plots 15 + +// +// Plot Buffers ... + +// +#define maBufferIndex 0 +double maBuffer[]; + +// +#property indicator_label1 "X121-XWZ MA" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLightSkyBlue +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +#define longSLBufferIndex 1 +double longSLBuffer[]; + +// +#property indicator_label2 "X121-XWZ Long SL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrOrange +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define shortSLBufferIndex 2 +double shortSLBuffer[]; + +// +#property indicator_label3 "X121-XWZ Short SL" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrOrange +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +#define upTrendBufferIndex 3 +double upTrendBuffer[]; + +// +#property indicator_label4 "X121-XWZ Trend Up" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrAqua +#property indicator_width4 3 + +// +#define downTrendBufferIndex 4 +double downTrendBuffer[]; + +// +#property indicator_label5 "X121-XWZ Trend Down" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrMagenta +#property indicator_width5 3 + +// +#define bullishMomentumBufferIndex 5 +double bullishMomentumBuffer[]; + +// +#property indicator_label6 "X121-XWZ Bull Momentum" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrAqua +#property indicator_width6 3 + +// +#define bearishMomentumBufferIndex 6 +double bearishMomentumBuffer[]; + +// +#property indicator_label7 "X121-XWZ Bear Momentum" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrMagenta +#property indicator_width7 3 + +// +#define bullishRejectionBufferIndex 7 +double bullishRejectionBuffer[]; + +// +#property indicator_label8 "X121-XWZ Bull Rejection" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrAqua +#property indicator_width8 3 + +// +#define bearishRejectionBufferIndex 8 +double bearishRejectionBuffer[]; + +// +#property indicator_label9 "X121-XWZ Bear Rejection" +#property indicator_type9 DRAW_ARROW +#property indicator_color9 clrMagenta +#property indicator_width9 3 + +// +#define bullishPinBufferIndex 9 +double bullishPinBuffer[]; + +// +#property indicator_label10 "X121-XWZ Bull Pin" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrAqua +#property indicator_width10 3 + +// +#define bearishPinBufferIndex 10 +double bearishPinBuffer[]; + +// +#property indicator_label11 "X121-XWZ Bear Pin" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrMagenta +#property indicator_width11 3 + +// +#define bullishEngulfBufferIndex 11 +double bullishEngulfBuffer[]; + +// +#property indicator_label12 "X121-XWZ Bull Engulf" +#property indicator_type12 DRAW_ARROW +#property indicator_color12 clrAqua +#property indicator_width12 3 + +// +#define bearishEngulfBufferIndex 12 +double bearishEngulfBuffer[]; + +// +#property indicator_label13 "X121-XWZ Bear Engulf" +#property indicator_type13 DRAW_ARROW +#property indicator_color13 clrMagenta +#property indicator_width13 3 + +// +#define swingLowBufferIndex 13 +double swingLowBuffer[]; + +// +#property indicator_label14 "X121-XWZ Swing Low" +#property indicator_type14 DRAW_ARROW +#property indicator_color14 clrAqua +#property indicator_width14 3 + +// +#define swingHighBufferIndex 14 +double swingHighBuffer[]; + +// +#property indicator_label15 "X121-XWZ Swing High" +#property indicator_type15 DRAW_ARROW +#property indicator_color15 clrMagenta +#property indicator_width15 3 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 14; + +// +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +#define adxBufferIndex mLastBufferIndex + 2 +double adxBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// MA Handler ... +int maHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +// ADX Handler ... +int adxHandler = INVALID_HANDLE; + +// +XCAlert *mXWZAlert; +XBarTracker mXWZBarTracker; +CArrayObj mXWZDrawnObjects; +XCPOIDrawer *mXWZPOIDrawer; +XCBarAnalyser *mXWZBarAnalyser; + +// +// POI(s) ... + +// +bool mXWZDetectOrderBlocks = true; +bool mXWZDetectFairValueGaps = true; +bool mXWZDetectSupplyZones = true; +bool mXWZDetectDemandZones = true; + +// +bool mXWZIgnoreUnActivateds = true; + +// +bool mXWZForceStarteds = true; +bool mXWZForceUnBreaked = true; +bool mXWZForceActivation = true; + +// +int mXWZSuResRange = 21; +int mXWZOBFVGSameBars = 3; + +// +// Un Activated POI(s) ... +XCFVG *mXWZUnActivatedFVGs[]; +XCOrderBlock *mXWZUnActivatedOBs[]; +XCSupplyZone *mXWZUnActivatedSupplyZones[]; +XCDemandZone *mXWZUnActivatedDemandZones[]; + +// +// Activated POI(s) ... +XCFVG *mXWZActivatedFVGs[]; +XCOrderBlock *mXWZActivatedOBs[]; +XCSupplyZone *mXWZActivatedSupplyZones[]; +XCDemandZone *mXWZActivatedDemandZones[]; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + mXWZDrawnObjects.Clear(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // MA ... + maHandler = iMA( + _Symbol, + _Period, + maLength, + 0, + maMethod, + appliedTo // + ); + bool isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Initialize Bar Tracker ... + mXWZBarTracker.Init( + _Symbol, + _Period // + ); + + // + mXWZPOIDrawer = new XCPOIDrawer(); + ConfigurePOIDrawer(); + + // + mXWZAlert = new XCAlert(); + ConfigureAlert(); + + // + mXWZBarAnalyser = new XCBarAnalyser(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(maHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(adxHandler); + + // + mXWZDrawnObjects.Clear(); + + // + ZeroMemory(mXWZAlert); + ZeroMemory(mXWZPOIDrawer); + ZeroMemory(mXWZBarAnalyser); + + // + Clean(mXWZActivatedOBs); + Clean(mXWZActivatedFVGs); + Clean(mXWZActivatedSupplyZones); + Clean(mXWZActivatedDemandZones); + + // + Clean(mXWZUnActivatedOBs); + Clean(mXWZUnActivatedFVGs); + Clean(mXWZUnActivatedSupplyZones); + Clean(mXWZUnActivatedDemandZones); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // MA ... + int maCalculatedBars = BarsCalculated(maHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // MA ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + + // + // ATR ... + int copiedAtr = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // ADX ... + int copiedAdxs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMas > 0 && + // + // ATR ... + copiedAtr > 0 && + // + // ADX ... + copiedAdxs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 && + // + // ADX ... + adxLength > 0 && + adxThreshold > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(maLength, atrLength); + result = MathMax(result, adxLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // MA Buffer ... + + // + ENUM_DRAW_TYPE maDrawType = showMA ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showMA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, maDrawType); + + // + PlotIndexSetDouble(maBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // LONG SL Buffer ... + + // + ENUM_DRAW_TYPE longSLDrawType = showLongSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(longSLBuffer, true); + SetIndexBuffer(longSLBufferIndex, longSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(longSLBufferIndex, PLOT_SHOW_DATA, showLongSL); + PlotIndexSetInteger(longSLBufferIndex, PLOT_DRAW_TYPE, longSLDrawType); + + // + PlotIndexSetDouble(longSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // SHORT SL Buffer ... + + // + ENUM_DRAW_TYPE shortSLDrawType = showShortSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(shortSLBuffer, true); + SetIndexBuffer(shortSLBufferIndex, shortSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(shortSLBufferIndex, PLOT_SHOW_DATA, showShortSL); + PlotIndexSetInteger(shortSLBufferIndex, PLOT_DRAW_TYPE, shortSLDrawType); + + // + PlotIndexSetDouble(shortSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // UP Trend ... + + // + ENUM_DRAW_TYPE upTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(upTrendBuffer, true); + SetIndexBuffer(upTrendBufferIndex, upTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(upTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_DRAW_TYPE, upTrendDrawType); + + // + PlotIndexSetDouble(upTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_ARROW, upTrendArrowCode); + + // + // DOWN Trend ... + + // + ENUM_DRAW_TYPE downTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(downTrendBuffer, true); + SetIndexBuffer(downTrendBufferIndex, downTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(downTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_DRAW_TYPE, downTrendDrawType); + + // + PlotIndexSetDouble(downTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_ARROW, downTrendArrowCode); + + // + // Bullish Momentum ... + + // + ENUM_DRAW_TYPE bullishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishMomentumBuffer, true); + SetIndexBuffer(bullishMomentumBufferIndex, bullishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_DRAW_TYPE, bullishMomentumDrawType); + + // + PlotIndexSetDouble(bullishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_ARROW, bullishMomentumArrowCode); + + // + // Bearish Momentum ... + + // + ENUM_DRAW_TYPE bearishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishMomentumBuffer, true); + SetIndexBuffer(bearishMomentumBufferIndex, bearishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_DRAW_TYPE, bearishMomentumDrawType); + + // + PlotIndexSetDouble(bearishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_ARROW, bearishMomentumArrowCode); + + // + // Bullish Rejection ... + + // + ENUM_DRAW_TYPE bullishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishRejectionBuffer, true); + SetIndexBuffer(bullishRejectionBufferIndex, bullishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_DRAW_TYPE, bullishRejectionDrawType); + + // + PlotIndexSetDouble(bullishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_ARROW, bullishRejectionArrowCode); + + // + // Bearish Rejection ... + + // + ENUM_DRAW_TYPE bearishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishRejectionBuffer, true); + SetIndexBuffer(bearishRejectionBufferIndex, bearishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_DRAW_TYPE, bearishRejectionDrawType); + + // + PlotIndexSetDouble(bearishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_ARROW, bearishRejectionArrowCode); + + // + // Bullish Pin ... + + // + ENUM_DRAW_TYPE bullishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishPinBuffer, true); + SetIndexBuffer(bullishPinBufferIndex, bullishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_DRAW_TYPE, bullishPinDrawType); + + // + PlotIndexSetDouble(bullishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_ARROW, bullishPinArrowCode); + + // + // Bearish Pin ... + + // + ENUM_DRAW_TYPE bearishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishPinBuffer, true); + SetIndexBuffer(bearishPinBufferIndex, bearishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_DRAW_TYPE, bearishPinDrawType); + + // + PlotIndexSetDouble(bearishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_ARROW, bearishPinArrowCode); + + // + // Bullish Engulf ... + + // + ENUM_DRAW_TYPE bullishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishEngulfBuffer, true); + SetIndexBuffer(bullishEngulfBufferIndex, bullishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_DRAW_TYPE, bullishEngulfDrawType); + + // + PlotIndexSetDouble(bullishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_ARROW, bullishEngulfArrowCode); + + // + // Bearish Engulf ... + + // + ENUM_DRAW_TYPE bearishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishEngulfBuffer, true); + SetIndexBuffer(bearishEngulfBufferIndex, bearishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_DRAW_TYPE, bearishEngulfDrawType); + + // + PlotIndexSetDouble(bearishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_ARROW, bearishEngulfArrowCode); + + // + // Swing Low ... + + // + ENUM_DRAW_TYPE swingLowDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_DRAW_TYPE, swingLowDrawType); + + // + PlotIndexSetDouble(swingLowBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_ARROW, swingLowArrowCode); + + // + // Swing High ... + + // + ENUM_DRAW_TYPE swingHighDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_DRAW_TYPE, swingHighDrawType); + + // + PlotIndexSetDouble(swingHighBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_ARROW, swingHighArrowCode); + + // + // DATA Buffers ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculatedPOIs( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + maBuffer[barIndex] = 0; + atrBuffer[barIndex] = 0; + adxBuffer[barIndex] = 0; + longSLBuffer[barIndex] = 0; + shortSLBuffer[barIndex] = 0; + upTrendBuffer[barIndex] = 0; + swingLowBuffer[barIndex] = 0; + swingHighBuffer[barIndex] = 0; + downTrendBuffer[barIndex] = 0; + bullishPinBuffer[barIndex] = 0; + bearishPinBuffer[barIndex] = 0; + bullishEngulfBuffer[barIndex] = 0; + bearishEngulfBuffer[barIndex] = 0; + bullishMomentumBuffer[barIndex] = 0; + bearishMomentumBuffer[barIndex] = 0; + bullishRejectionBuffer[barIndex] = 0; + bearishRejectionBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Prepare Requirements ... + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + int pIndex = pBar.Index(); + + // + // Calculate Applied Price ... + double iPrice = GetAppliedPrice( + appliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + double iMa = maBuffer[bar_index]; + double iMaPrev = maBuffer[pIndex]; + double iAtr = atrBuffer[bar_index]; + double iAdx = adxBuffer[bar_index]; + double iAppliedAtr = iAtr * atrMultiplier; + + // + double points = GetPoints(_Symbol); + double points10 = 10 * points; + + // + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // SL Buffers ... + + // + double iLongSL = iPrice - iAppliedAtr; + double iShortSL = iPrice + iAppliedAtr; + + // + longSLBuffer[bar_index] = iLongSL; + shortSLBuffer[bar_index] = iShortSL; + + // + // Trend Buffers ... + + // + bool isUpTrend = + // + iPrice > iMa && + iBar.low < iMa && + iAdx > adxThreshold + // + ; + + // + bool isDownTrend = + // + iPrice < iMa && + iBar.high > iMa && + iAdx > adxThreshold + // + ; + + // + double upTrendValue = 0; + double downTrendValue = 0; + if (isUpTrend) + { + upTrendValue = iBar.low; + } + if (isDownTrend) + { + downTrendValue = iBar.high; + } + + // + upTrendBuffer[bar_index] = upTrendValue; + downTrendBuffer[bar_index] = downTrendValue; + + // + // Momentum Buffers ... + + // + bool isMomentum = mXWZBarAnalyser + .IsMomentumBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + if (isMomentum) + { + // + double iBullMomentumValue = 0; + double iBearMomentumValue = 0; + + // + if (isBullishMomentum) + { + // + double selectedValue = iBar.low; + + // + iBullMomentumValue = selectedValue; + } + + // + if (isBearishMomentum) + { + // + double selectedValue = iBar.high; + + // + iBearMomentumValue = selectedValue; + } + + // + bullishMomentumBuffer[bar_index] = iBullMomentumValue; + bearishMomentumBuffer[bar_index] = iBearMomentumValue; + } + + // + // Rejection Buffers ... + + // + bool isRejection = mXWZBarAnalyser + .IsRejectionBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishRejection = + isRejection && + IsBullish(iDir); + bool isBearishRejection = + isRejection && + IsBearish(iDir); + if (isRejection) + { + // + double iBullRejectionValue = 0; + double iBearRejectionValue = 0; + + // + if (isBullishRejection) + { + // + double selectedValue = iBar.low; + + // + iBullRejectionValue = selectedValue; + } + + // + if (isBearishRejection) + { + // + double selectedValue = iBar.high; + + // + iBearRejectionValue = selectedValue; + } + + // + bullishRejectionBuffer[bar_index] = iBullRejectionValue; + bearishRejectionBuffer[bar_index] = iBearRejectionValue; + } + + // + // Pin Buffers ... + + // + bool isPin = mXWZBarAnalyser + .IsPinBar( + iBar, + iDir, + 0, // Extends ... + 50, // Shadow Percent ... + 25 // Body Percent ... + ); + bool isBullishPin = + isPin && + IsBullish(iDir); + bool isBearishPin = + isPin && + IsBearish(iDir); + if (isPin) + { + // + double iBullPinValue = 0; + double iBearPinValue = 0; + + // + if (isBullishPin) + { + // + double selectedValue = iBar.low; + + // + iBullPinValue = selectedValue; + } + + // + if (isBearishPin) + { + // + double selectedValue = iBar.high; + + // + iBearPinValue = selectedValue; + } + + // + bullishPinBuffer[bar_index] = iBullPinValue; + bearishPinBuffer[bar_index] = iBearPinValue; + } + + // + // Engulf Buffers ... + + // + bool isEngulf = mXWZBarAnalyser + .IsEngulfBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishEngulf = + isEngulf && + IsBullish(iDir); + bool isBearishEngulf = + isEngulf && + IsBearish(iDir); + if (isEngulf) + { + // + double iBullEngulfValue = 0; + double iBearEngulfValue = 0; + + // + if (isBullishEngulf) + { + // + double selectedValue = iBar.low; + + // + iBullEngulfValue = selectedValue; + } + + // + if (isBearishEngulf) + { + // + double selectedValue = iBar.high; + + // + iBearEngulfValue = selectedValue; + } + + // + bullishEngulfBuffer[bar_index] = iBullEngulfValue; + bearishEngulfBuffer[bar_index] = iBearEngulfValue; + } + + // + // Swing Buffers ... + + // + bool isSwing = mXWZBarAnalyser + .IsSwing( + iBar, + iDir, + 2 // Range ... + ); + bool isSwingLow = + isSwing && + IsBullish(iDir); + bool isSwingHigh = + isSwing && + IsBearish(iDir); + if (isSwing) + { + // + double iSwingLowValue = 0; + double iSwingHighValue = 0; + + // + if (isSwingLow) + { + // + double selectedValue = iBar.low; + + // + iSwingLowValue = selectedValue; + } + + // + if (isSwingHigh) + { + // + double selectedValue = iBar.high; + + // + iSwingHighValue = selectedValue; + } + + // + swingLowBuffer[bar_index] = iSwingLowValue; + swingHighBuffer[bar_index] = iSwingHighValue; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + pBar.Clean(); +} + +// +// POIS Functions ... + +// +void ConfigurePOIDrawer() +{ + // + if (mXWZPOIDrawer == NULL) + { + return; + } + + // + mXWZPOIDrawer.Prefix(ShortName); + mXWZPOIDrawer.ChartIdentification(ChartID()); + mXWZPOIDrawer.SubWindowIdentification(0); + + // + mXWZPOIDrawer.BullishFVGWidth(2); + mXWZPOIDrawer.BullishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BullishFVGColor(clrAqua); + + // + mXWZPOIDrawer.BearishFVGWidth(2); + mXWZPOIDrawer.BearishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BearishFVGColor(clrMagenta); + + // + mXWZPOIDrawer.SupportZoneWidth(1); + mXWZPOIDrawer.SupportZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.SupportZoneColor(clrLime); + + // + mXWZPOIDrawer.ResistanceZoneWidth(1); + mXWZPOIDrawer.ResistanceZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.ResistanceZoneColor(clrRed); + + // + mXWZPOIDrawer.BullishOrderBlockWidth(3); + mXWZPOIDrawer.BullishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BullishOrderBlockColor(clrAqua); + + // + mXWZPOIDrawer.BearishOrderBlockWidth(3); + mXWZPOIDrawer.BearishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BearishOrderBlockColor(clrMagenta); +} + +// +void ConfigureAlert() +{ + // + mXWZAlert.SetPrefix(ShortName); + + // + mXWZAlert.SetPushAlerts(mXWZPushAlerts); + mXWZAlert.SetMailAlerts(mXWZMailAlerts); + mXWZAlert.SetEnableAlerts(mXWZEnableAlerts); + mXWZAlert.SetTerminalAlerts(mXWZTerminalAlerts); +} + +// +void CalculatedPOIs( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + + // + // POI ... + DetectPOIs(iBar); + UpdatePOIs(iBar); + DrawPOIs(); + + // + iBar.Clean(); + pBar.Clean(); +} + +// +bool CanDetectPOIs() +{ + // + bool result = false; + + // + result = + // + mXWZDetectOrderBlocks || + mXWZDetectFairValueGaps || + mXWZDetectSupplyZones || + mXWZDetectDemandZones + // + ; + + // + return result; +} + +// +void DetectPOIs( + XOHCL &bar // +) +{ + // + if (!CanDetectPOIs()) + { + return; + } + + // + int barIndex = bar.Index(); + + // + if (barIndex <= 0) + { + return; + } + + // + DetectOrderBlock(bar); + DetectSupplyZone(bar); + DetectDemandZone(bar); + DetectFairValueGap(bar); + + // +} + +// +void UpdatePOIs( + XOHCL &bar // +) +{ + // + int count = 0; + bool has = false; + + // + // OrderBlock(s) ... + + // + has = HasChild(mXWZUnActivatedOBs); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedOBs, + bar.time // + ); + } + + // + // Fair Value Gaps ... + + // + has = HasChild(mXWZUnActivatedFVGs); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedFVGs, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedFVGs); + } + + // + // Supply Zones ... + + // + has = HasChild(mXWZUnActivatedSupplyZones); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedSupplyZones, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedSupplyZones); + } + + // + // Demand Zones ... + + // + has = HasChild(mXWZUnActivatedDemandZones); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedDemandZones, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedDemandZones); + } +} + +// +void DrawPOIs() +{ + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + if (!showPOIs) + { + return; + } + + // + // Order Blocks ... + if (showOrderBlocks) + { + // + bool showBullishOrderBlocks = true; + bool showBearishOrderBlocks = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedOBs[i].IsBullish(); + + // + if ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + mXWZUnActivatedOBs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Fair Value Gaps ... + if (showFairValueGaps) + { + // + bool showBullishFairValueGaps = true; + bool showBearishFairValueGaps = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedFVGs[i].IsBullish(); + + // + if ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + mXWZUnActivatedFVGs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Supply Zones ... + if (showSupplyZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedSupplyZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupplyZone( + mXWZUnActivatedSupplyZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedSupplyZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + } + } + } + + // + // Demand Zones ... + if (showDemandZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedDemandZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateDemandZone( + mXWZUnActivatedDemandZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedDemandZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + } + } + } + + // + ChartRedraw(); + + // +} + +// +// +// + +// +// Detect Order Block ... +void DetectOrderBlock(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectOrderBlocks) + { + return; + } + + // + int iBarIndex = bar.Index(orderBlockTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + orderBlockTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir; + has = mXWZBarAnalyser.HasOrderBlock( + iBar, + zoneBar, + zoneDir, + mXWZOBFVGSameBars // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCOrderBlock *zone; + zone = new XCOrderBlock(); + has = zone.Init( + zoneBar, + zoneDir // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + if (!mXWZIgnoreUnActivateds) + { + // + zone.To(activationBar.time); + + // + Add( + zone, + mXWZActivatedOBs // + ); + } + + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedOBs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedOBs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedOBs // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// +// Detect Fair Value Gap ... +void DetectFairValueGap(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectFairValueGaps) + { + return; + } + + // + int iBarIndex = bar.Index(fairValueGapTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + fairValueGapTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + XOHCL zoneEndBar; + XOHCL zoneStartBar; + ENUM_X_DIRECTION zoneDir; + has = mXWZBarAnalyser.HasFairValueGap( + iBar, + zoneStartBar, + zoneEndBar, + zoneDir, + mXWZOBFVGSameBars // + ); + + // + if (!has) + { + // + zoneEndBar.Clean(); + zoneStartBar.Clean(); + return; + } + + // + XCFVG *zone; + zone = new XCFVG(); + has = zone.Init( + zoneStartBar, + zoneEndBar, + zoneDir // + ); + + // + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + ZeroMemory(zone); + startedBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + ZeroMemory(zone); + breakedBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedFVGs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedFVGs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedFVGs // + ); + } + + // + iBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); +} + +// +// Supply Zone ... +void DetectSupplyZone(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectSupplyZones) + { + return; + } + + // + int iBarIndex = bar.Index(supDemTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + supDemTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + int range = mXWZSuResRange * 2; + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir = X_DIRECTION_BEARISH; + has = mXWZBarAnalyser.HasResistance( + iBar, + zoneBar, + range // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCSupplyZone *zone; + zone = new XCSupplyZone(); + has = zone.Init( + zoneBar, + range, + true // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedSupplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedSupplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedSupplyZones // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// +// Demand Zone ... +void DetectDemandZone(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectDemandZones) + { + return; + } + + // + int iBarIndex = bar.Index(supDemTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + supDemTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + int range = mXWZSuResRange * 2; + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir = X_DIRECTION_BULLISH; + has = mXWZBarAnalyser.HasSupport( + iBar, + zoneBar, + range // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCDemandZone *zone; + zone = new XCDemandZone(); + has = zone.Init( + zoneBar, + range, + true // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedDemandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedDemandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedDemandZones // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Documents/JsModules/mqlHelper.js b/BKPS/14040626/Documents/JsModules/mqlHelper.js new file mode 100644 index 0000000..8fe4e41 --- /dev/null +++ b/BKPS/14040626/Documents/JsModules/mqlHelper.js @@ -0,0 +1,19 @@ +/** + * XMQL Helper CLI Tools ... + * a module for handle MQL5 Commands running ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// Read Command Arguments ... +let cmdName = process.argv[2]; + +// +XProjectTools.runCommand(cmdName); diff --git a/BKPS/14040626/Documents/JsModules/prepareXCATBEA.js b/BKPS/14040626/Documents/JsModules/prepareXCATBEA.js new file mode 100644 index 0000000..797e213 --- /dev/null +++ b/BKPS/14040626/Documents/JsModules/prepareXCATBEA.js @@ -0,0 +1,35 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XCATBEA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "XCATBEA/*", // XCATBEA Projects ... + "Indicators/x-saherelm.x121.xcatb", // Required Indicators + "Helpers/x-saherelm.x121.xcatb.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.x121.xcatb.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject( + projectName, + projectResources + ); +} + + + diff --git a/BKPS/14040626/Documents/JsModules/x-color.tools.js b/BKPS/14040626/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/BKPS/14040626/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/14040626/Documents/JsModules/x-file.tools.js b/BKPS/14040626/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..2a3535d --- /dev/null +++ b/BKPS/14040626/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/14040626/Documents/JsModules/x-mql-project.tools.js b/BKPS/14040626/Documents/JsModules/x-mql-project.tools.js new file mode 100644 index 0000000..4a507a4 --- /dev/null +++ b/BKPS/14040626/Documents/JsModules/x-mql-project.tools.js @@ -0,0 +1,494 @@ +/** + * XProject Tools Module ... + * a module for handle MQL5 Projects Compile and Packing ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const execSync = require("child_process").execSync; +const XFileTools = require("./Documents/JsModules/x-file.tools"); +const XShellTools = require("./Documents/JsModules/x-shell.tools"); +const XColorTools = require("./Documents/JsModules/x-color.tools"); +const XTypeTools = require("./Documents/JsModules/x-type-detector.tools"); + +// +// Definitions ... +const packsPath = XFileTools.joinPath(".", "Packs"); +const workspacePaths = [ + "Classes", // Required Classes + "Experts", // Expert Advisers + "Helpers", // Indicator's Helpers Classes + "Indicators", // Required Indicators + "Libraries", // Required Libraries + "XCATBEA", // XCATBEA Projects ... +]; + +// +//#region Tools ... + +/** + * Handle Compile and Pack Projects ... + * + * @param {string} projectName + * @param {string[]} resources + * @param {boolean} forceCleanup + * @param {boolean} forceCompileIndicators + */ +async function prepareProject( + projectName = "", + resources = [], + forceCleanup = true, + forceCompileIndicators = true +) { + // + // Check Resources Has Child ... + let isValidArgs = + resources.length > 0 && + XTypeTools.isArray(resources); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Resource List ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Check Project Name is Valid ... + isValidArgs = + projectName.length > 0 && + XTypeTools.isString(projectName); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Empty Project Name ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Extract Required to Compile Resources List ... + let compileList = await extractResources(resources, true); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + + // + // Extract Required to Pack Resources List ... + let packList = await extractResources(resources, false); + if (!packList || packList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Pack Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Prepare Pack Folder Exists ... + let isExists = XFileTools.isDirectoryExists(packsPath); + if (!isExists) { + XFileTools.createDirectory(packsPath); + } + + // + // Check Folder Exists or not ... + // if Exists Remove it ... + // Create Project Folder on Packs ... + const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName); + isExists = XFileTools.isDirectoryExists(prjFolderOnPacks); + if (isExists) { + await XFileTools.removeDirectory(prjFolderOnPacks, true); + } + XFileTools.createDirectory(prjFolderOnPacks); + + // + // Loop through Files ... + for (const f of packList) { + // + // Prepare Destination Path ... + const fBasePath = XFileTools.basename(f); + let fDestPath = f.replace(fBasePath, ""); + fDestPath = fDestPath.substring(0, fDestPath.length - 1); + fDestPath = XFileTools.joinPath(prjFolderOnPacks, fDestPath); + + // + const isFDestPathExists = XFileTools.isDirectoryExists(fDestPath); + if (!isFDestPathExists) { + XFileTools.createDirectory(fDestPath); + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to copy: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue), + XColorTools.applyForegroundColor(" to : ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(fDestPath, XColorTools.COLOR_NAMES.Magenta) + ); + + // + let result = await XFileTools.copyFile(f, fDestPath); + if (result) { + // + const msg = "copy successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "copy failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Project: ", XColorTools.COLOR_NAMES.Green), + XColorTools.applyForegroundColor(projectName, XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(" Compiled and Packed Successfully ...", XColorTools.COLOR_NAMES.Green), + ); + + // + // Cleanup WorkSpace if Provided ... + if (forceCleanup) { + await cleanupWorkSpace(); + } + + // + // Compile Indicators ... + if (forceCompileIndicators) { + await compile("Indicators"); + } +} + +/** + * Extract required Files List ... + * + * @param {boolean} forCompile + * + * @returns Promise + */ +async function extractResources( + resources = [], + forCompile = true +) { + // + let result = []; + + // + // Loop Through Project Resources and Extract Files List to Compile ... + for (const resource of resources) { + // + // Prepare Normalized Resource Path ... + let resourcePath = XFileTools.joinPath(".", resource); + + // + // Handle Wild Card Resources ... + if (resourcePath.endsWith("//*") || + resourcePath.endsWith("\\*")) { + // + resourcePath = resourcePath.substring(0, resourcePath.length - 2); + const files = await XFileTools.extractFiles( + resourcePath, + forCompile ? [".mq5", ".mq4"] : [".ex5", ".ex4"] + ); + + // + result = result.concat(files); + } + // + // Handle Direct File Resources ... + else { + // + // Check MQL 5 Version ... + let fileResourcePath = resourcePath + (forCompile ? ".mq5" : ".ex5"); + + // + // Check File Exists ... + let isExists = XFileTools.isFileExists(fileResourcePath); + if (!isExists) { + // + // Check MQL 4 Version ... + fileResourcePath = resourcePath + (forCompile ? ".mq4" : ".ex4"); + isExists = XFileTools.isFileExists(fileResourcePath); + } + + // + // Add File Path to Files List if Exists ... + if (isExists) { + result.push(fileResourcePath); + } + } + } + + // + return result; +} + +/** + * try to compile a file ... + * @param {string} f + * @param {number} numberOfTries + */ +async function recursiveTriesToCompileFile(f = "", numberOfTries = 0) { + // + let result = await handleFileCompile(f); + if (result) { + // + const msg = "compiled successfully ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green)); + return result; + } else { + // + if (numberOfTries < 10) { + // + numberOfTries++; + + // + const msg = "retry (" + (numberOfTries + 1) + ") ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.LightMagenta)); + await recursiveTriesToCompileFile(f, numberOfTries); + } else { + // + const msg = "failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + + // + return false; + } + } +} + +/** + * execute compile task on Specific File ... + * @param {string} f file path to Execute Compile task ... + * @returns + */ +async function handleFileCompile(f = "") { + // + let result = false; + + // + let exResult = await compileMQLFile(f); + if (exResult.includes("0 errors")) { + result = true; + } else { + result = false; + } + + // + return result; +} + +/** + * Compile Specific MQL File ... + * + * @param {string} path MQL file path ... + * @returns + */ +async function compileMQLFile(path = "") { + // + // Check File Exists ... + const isExists = XFileTools.isFileExists(path); + if (!isExists) { + // + const msg = "file not found ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const ext = XFileTools.getFileExtension(path); + if (ext !== ".mq5" && ext !== "mq4") { + // + const msg = "invalid file extension ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const cwd = __dirname; + const cmd = "compile.cmd " + path; + + // + const result = await XShellTools.execute(cmd, cwd); + return result; +} + +/** + * Run Specified Command in workspace ... + * + * @param {string} cmd + * @returns + */ +async function runCommand(cmd = "") { + // + // Validate Args ... + let isValidArgs = cmd.length > 0 && + XTypeTools.isString(cmd); + + // + // Validate Commands ... + if (isValidArgs) { + // + // Check Available Commands ... + isValidArgs = + cmd === "*" || + cmd === "cleanup" || + workspacePaths.includes(cmd) || + workspacePaths.map(x => x.toLowerCase(x)).includes(cmd.toLowerCase()); + } + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Compile ... + if (cmd == "*") { + await compileWorkSpace(); + } else if (cmd == "cleanup") { + await cleanupWorkSpace(); + } else { + // + // Select Workspace to Compile ... + const folder = workspacePaths + .find(x => x.toLowerCase() === cmd.toLowerCase()); + isValidArgs = + XTypeTools.isString(folder) && + folder.length > 0; + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Extract Required to Compile Resources List ... + let compileList = await XFileTools.extractFiles( + folder, + [".mq5", ".mq4"] + ); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + } +} + +/** + * Cleanup Workspace compiled files ... + */ +async function cleanupWorkSpace() { + // + for (const path of workspacePaths) { + // + const fSourcePath = XFileTools.joinPath(".", path); + const filesToRemove = await XFileTools.extractFiles(fSourcePath, [".ex5", ".ex4"]); + for (const f of filesToRemove) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Remove: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + let result = await XFileTools.removeFile(f); + if (result) { + // + const msg = "removed successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "removed failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + } +} + +/** + * Compile Workspace ... + */ +async function compileWorkSpace() { + // + for (const path of workspacePaths) { + await runCommand(path); + } +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + extractResources, + recursiveTriesToCompileFile, + handleFileCompile, + compileMQLFile, + runCommand, + cleanupWorkSpace, + compileWorkSpace, + prepareProject +} +//#endregion \ No newline at end of file diff --git a/BKPS/14040626/Documents/JsModules/x-shell.tools.js b/BKPS/14040626/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/BKPS/14040626/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/14040626/Documents/JsModules/x-type-detector.tools.js b/BKPS/14040626/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/BKPS/14040626/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/14040626/Documents/JsModules/x-value.tools.js b/BKPS/14040626/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/BKPS/14040626/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/14040626/Documents/Logs/x.xczones.full.filter.no-range.logs.xlog b/BKPS/14040626/Documents/Logs/x.xczones.full.filter.no-range.logs.xlog new file mode 100644 index 0000000..0fde107 --- /dev/null +++ b/BKPS/14040626/Documents/Logs/x.xczones.full.filter.no-range.logs.xlog @@ -0,0 +1,140 @@ +/////////////////////////////////////////////////////////////////////////// +// EURUSD: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.01.17 12:30:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2024.05.03 14:00:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2024.05.23 03:05:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.06.05 09:10:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.07.01 12:05:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.07.22 13:05:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.08.15 19:35:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2024.09.24 06:05:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.09.24 12:50:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.10.31 15:50:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2024.11.06 20:15:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.12.02 09:10:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2024.12.26 20:05:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2024.12.30 00:05:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2024.12.30 03:55:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2025.01.03 17:15:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2025.01.22 13:30:00 +X121 XCZone > EURUSDb,M5> BEARISH Zone Detected at: 2025.03.28 08:15:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2025.04.01 16:25:00 +X121 XCZone > EURUSDb,M5> BULLISH Zone Detected at: 2025.04.23 11:30:00 +/////////////////////////////////////////////////////////////////////////// +// GBPUSD: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.03.26 10:30:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.04.12 20:45:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.04.19 16:25:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.05.03 03:45:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.05.09 12:35:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.05.23 03:10:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.06.11 19:40:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.07.01 11:15:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.08.12 16:05:00 +X121 XCZone > GBPUSDb,M5> BEARISH Zone Detected at: 2024.08.16 17:05:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.09.02 03:25:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.11.06 20:15:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.11.11 02:25:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.11.11 11:55:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2024.12.26 20:05:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2025.01.27 23:10:00 +X121 XCZone > GBPUSDb,M5> BEARISH Zone Detected at: 2025.01.31 15:25:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2025.03.14 07:00:00 +X121 XCZone > GBPUSDb,M5> BEARISH Zone Detected at: 2025.03.26 17:20:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2025.04.02 17:35:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2025.04.04 03:35:00 +X121 XCZone > GBPUSDb,M5> BULLISH Zone Detected at: 2025.04.24 21:45:00 +/////////////////////////////////////////////////////////////////////////// +// USDCHF: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > USDCHFb,M5> BULLISH Zone Detected at: 2024.03.12 04:10:00 +X121 XCZone > USDCHFb,M5> BULLISH Zone Detected at: 2024.03.12 14:55:00 +X121 XCZone > USDCHFb,M5> BEARISH Zone Detected at: 2024.04.18 08:30:00 +X121 XCZone > USDCHFb,M5> BULLISH Zone Detected at: 2024.06.10 10:25:00 +X121 XCZone > USDCHFb,M5> BEARISH Zone Detected at: 2024.07.31 12:40:00 +X121 XCZone > USDCHFb,M5> BULLISH Zone Detected at: 2024.11.05 14:15:00 +X121 XCZone > USDCHFb,M5> BEARISH Zone Detected at: 2025.02.03 10:25:00 +X121 XCZone > USDCHFb,M5> BULLISH Zone Detected at: 2025.03.28 10:35:00 +X121 XCZone > USDCHFb,M5> BULLISH Zone Detected at: 2025.05.05 14:35:00 +/////////////////////////////////////////////////////////////////////////// +// DJ30.spot: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > DJ30.spot,M5> BEARISH Zone Detected at: 2024.01.23 16:00:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2024.03.18 10:55:00 +X121 XCZone > DJ30.spot,M5> BEARISH Zone Detected at: 2024.04.09 16:45:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2024.06.14 14:25:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2024.06.25 04:35:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2024.09.09 18:35:00 +X121 XCZone > DJ30.spot,M5> BEARISH Zone Detected at: 2024.09.11 16:35:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2024.09.20 06:40:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2024.10.22 17:50:00 +X121 XCZone > DJ30.spot,M5> BEARISH Zone Detected at: 2025.03.11 14:10:00 +X121 XCZone > DJ30.spot,M5> BEARISH Zone Detected at: 2025.03.11 18:00:00 +X121 XCZone > DJ30.spot,M5> BEARISH Zone Detected at: 2025.05.01 18:45:00 +X121 XCZone > DJ30.spot,M5> BULLISH Zone Detected at: 2025.05.15 05:40:00 +/////////////////////////////////////////////////////////////////////////// +// XAGUSD: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2024.01.08 16:05:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.02.13 05:10:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.03.19 03:35:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2024.03.22 02:20:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.04.01 10:50:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2024.04.15 13:00:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.04.22 18:05:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2024.05.08 17:15:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.07.11 22:55:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.07.25 12:05:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.07.26 09:15:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.08.15 22:35:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.08.29 22:50:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2024.09.20 03:30:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2024.10.01 10:10:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2024.11.28 06:20:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2025.01.15 04:35:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2025.02.11 03:25:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2025.02.17 18:55:00 +X121 XCZone > XAGUSDb,M5> BEARISH Zone Detected at: 2025.03.20 15:10:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2025.05.05 05:30:00 +X121 XCZone > XAGUSDb,M5> BULLISH Zone Detected at: 2025.05.12 14:05:00 +/////////////////////////////////////////////////////////////////////////// +// USDJPY: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2024.01.19 14:20:00 +X121 XCZone > USDJPYb,M5> BEARISH Zone Detected at: 2024.02.02 20:20:00 +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2024.03.28 17:55:00 +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2024.06.26 16:25:00 +X121 XCZone > USDJPYb,M5> BEARISH Zone Detected at: 2024.07.11 10:20:00 +X121 XCZone > USDJPYb,M5> BEARISH Zone Detected at: 2024.08.30 01:10:00 +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2024.09.23 14:25:00 +X121 XCZone > USDJPYb,M5> BEARISH Zone Detected at: 2024.10.07 06:30:00 +X121 XCZone > USDJPYb,M5> BEARISH Zone Detected at: 2024.11.13 21:20:00 +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2024.12.18 00:20:00 +X121 XCZone > USDJPYb,M5> BEARISH Zone Detected at: 2025.01.27 02:20:00 +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2025.03.27 08:25:00 +X121 XCZone > USDJPYb,M5> BULLISH Zone Detected at: 2025.05.08 09:20:00 +/////////////////////////////////////////////////////////////////////////// +// BTCUSD: +/////////////////////////////////////////////////////////////////////////// +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.06.05 15:45:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.06.12 05:00:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2024.06.19 18:30:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.07.30 00:40:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2024.08.08 21:50:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.08.19 19:55:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.10.06 00:15:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.10.17 03:35:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.11.12 16:50:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.11.18 16:15:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2024.12.17 01:50:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2024.12.17 17:15:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2024.12.27 04:45:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2025.01.22 09:35:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2025.02.12 18:45:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2025.03.19 09:25:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2025.03.19 22:35:00 +X121 XCZone > BTCUSD,M5> BEARISH Zone Detected at: 2025.04.13 15:25:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2025.04.15 03:35:00 +X121 XCZone > BTCUSD,M5> BULLISH Zone Detected at: 2025.05.16 02:35:00 diff --git a/BKPS/14040626/Documents/Temlates/signalling.function.template.mq5 b/BKPS/14040626/Documents/Temlates/signalling.function.template.mq5 new file mode 100644 index 0000000..3cbd45a --- /dev/null +++ b/BKPS/14040626/Documents/Temlates/signalling.function.template.mq5 @@ -0,0 +1,221 @@ + +// +// Detect Signals Based On XPV Indicator Golden Zones ... +// +bool HasTMPConditions( + ENUM_X_CYCLES cycle, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + X121SMCStrategySignalProviderData &provider, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + box.Clean(); + dir = X_DIRECTION_NONE; + + // + // Fil Selected Data ... + XPOIState cState; + X121Conditions cXConditions; + XPOIStateEvents cStateEvents; + XC121SMCCycleHelper *cHelper; + X121SMCCycleConditions cConditions; + result = provider.SelectCycle( + cycle, + cState, + cStateEvents, + cXConditions, + cHelper, + cConditions // + ); + if (!result) + { + // + cState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + cStateEvents.Clean(); + + // + return result; + } + + // + // Normalize Args ... + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int ppIDX = pIDX + 1; + + // + bool isBullish = false; + bool isBearish = false; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL pPBar; + + // + // Initial Bars ... + result = zBar.Init( + cState.symbol, + cState.period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(pPBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + cState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + + // + return result; + } + + // + // Checking Conditions ... + + // + // Summarize Conditions ... + + // + isBullish = + // + false + // + ; + + // + isBearish = + // + false + // + ; + + // + // Filling Requirements ... + result = + isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + box.dir = dir; + box.from = pPBar.time; + box.to = TimeCurrent(); + box.symbol = cBar.symbol; + box.period = cBar.period; + + // + double points = GetPoints(box.symbol); + + // + // Usually is Preffered SL ... + double pivot = 0; + + // + // Usually is Current Price or Entry Price ... + double point = GetEntry( + cBar.symbol, + dir // + ); + + // + box.upper = + isBullish + ? point + : pivot; + + // + box.lower = + isBullish + ? pivot + : point; + + // + XCPOIDrawer *drawer = provider.visionCycleHelper.mPOIDrawer; + bool drawBoxes = true; + if (drawBoxes) + { + // + if (box.IsValid()) { + // + XCBoxObject *iObj; + bool isCreated = drawer.DrawBox( + box, + iObj // + ); + + // + if (isCreated) { + // + // TODO: ... + } + } + } + } + + // + // Check All Conditions ... + result = + box.IsValid() && + HasDirection(dir) && + (isBullish || + isBearish); + + // + // Cleanup Resources ... + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + cState.Clean(); + cConditions.Clean(); + cConditions.Clean(); + ZeroMemory(cHelper); + cStateEvents.Clean(); + cXConditions.Clean(); + + // + return result; +} diff --git a/BKPS/14040626/Documents/Temlates/temp.pivot.detect.mq5 b/BKPS/14040626/Documents/Temlates/temp.pivot.detect.mq5 new file mode 100644 index 0000000..2104084 --- /dev/null +++ b/BKPS/14040626/Documents/Temlates/temp.pivot.detect.mq5 @@ -0,0 +1,83 @@ + + // + bool DetectPivot( + int barIndex, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() && + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + XCAPviot pivot; + datetime cTime = zBar.time; + string symbol = zBar.symbol; + string period = zBar.period; + + // + // Reading Conditional Values ... + + // + // Prepare Conditinal Conditions ... + + // + bool hasStartCondition = false; + bool hasContinuationCondition = false; + bool hasEndCondition = false; + + // + // ReInstance Pivot ... + if (hasStartConditions) + { + // + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + } + + // + pivot.Clean(); + + // + return result; + } diff --git a/BKPS/14040626/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 b/BKPS/14040626/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 new file mode 100644 index 0000000..297e0b0 --- /dev/null +++ b/BKPS/14040626/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 @@ -0,0 +1,542 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XEATemplate +// Description: a Template For Exper Advisors +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XEATemplate" +#property strict + +// +#define ShortName "XEATemplate" + +// +// Imports ... +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() { + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() { + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCHelper = new XSCXCTHelper(); + result = eaCHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // TODO: Fix This ... + result = true; + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + // TODO: Complete this ... +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } +} + +// diff --git a/BKPS/14040626/Documents/Temlates/x-saherelm.x-panel.ea.mq5 b/BKPS/14040626/Documents/Temlates/x-saherelm.x-panel.ea.mq5 new file mode 100644 index 0000000..08417d4 --- /dev/null +++ b/BKPS/14040626/Documents/Temlates/x-saherelm.x-panel.ea.mq5 @@ -0,0 +1,575 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XPanelEA +// Description: an Exper Advisor which used Panels +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XPanelEA" +#property strict + +// +#define ShortName "XPANELEA" + +// +// Imports ... +#include "../Classes/x-saherelm.x-app-dialog.class.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCTHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +XCAppDialog eaMainWindow; // EA Main Dialog ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Apply Chart Event on Main Window ... + eaMainWindow.ChartEvent(id, lparam, dparam, sparam); + + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCTHelper = new XSCXCTHelper(); + result = eaCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCTHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // Initialize Application Main Window ... + result = eaMainWindow.Create( + ChartID(), + ShortName, // Dialog Name ... + 0, // SubWindow ... + 10, // X1 ... + 35, // Y1 ... + 300, // X2 ... + 200 // Y2 ... + ); + + // + // Configuring Dialog ... + // eaMainWindow.MinimizeButton(false); // Hide Minimize Button ... + // eaMainWindow.CloseButton(false); // Hide Close Button ... + eaMainWindow.BackgroundColor(clrBlack); + // result = true; + + // + // Try To Run Main Window ... + if (result) + { + eaMainWindow.Run(); + } + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + eaMainWindow.Destroy(); +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } +} + +// diff --git a/BKPS/14040626/Documents/Temlates/xwz.signal.senario.template.mq5 b/BKPS/14040626/Documents/Temlates/xwz.signal.senario.template.mq5 new file mode 100644 index 0000000..f9f6052 --- /dev/null +++ b/BKPS/14040626/Documents/Temlates/xwz.signal.senario.template.mq5 @@ -0,0 +1,187 @@ + + // + // Senario 3: + // ---------- + bool useSenario3 = false; + bool isSenario3Happend = false; + bool isSenario3Bullish = false; + bool isSenario3Bearish = false; + if (useSenario3) + { + // + // Senario 3 Bullish Conditions ... + isSenario3Bullish = false; + + // + // Senario 3 Bearish Conditions ... + isSenario3Bearish = false; + + // + // Filling Requirements using Senario 3 ... + isSenario3Happend = + isSenario3Bullish || + isSenario3Bearish; + if (isSenario3Happend) + { + // + dir = + isSenario3Bullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + box.dir = dir; + box.to = TimeCurrent(); + box.symbol = provider + .decisionXConditions + .symbol; + box.period = provider + .decisionXConditions + .period; + + // + int fromIDX = -1; + if (isSenario3Bullish) + { + // + double vale = provider + .decisionXConditions + .valesBuffer[cIDX]; + + // + box.lower = vale; + + // + box.upper = provider + .decisionXConditions + .valesGoldenBuffer[cIDX]; + + // + int lowerValeIDX = -1; + double lowerVale = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetLowerVale( + lowerValeIDX, + vale, + cBar.Index() // + ); + + // + int higherValeIDX = -1; + double higherVale = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetHigherVale( + higherValeIDX, + vale, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = + lowerValeIDX < higherValeIDX + ? lowerValeIDX + : higherValeIDX; + } + else if (IsValidIndex(lowerValeIDX) && + !IsValidIndex(higherValeIDX)) + { + // + fromIDX = lowerValeIDX; + } + else if (!IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = higherValeIDX; + } + } + else + { + // + double peak = provider + .decisionXConditions + .peaksBuffer[cIDX]; + + // + box.upper = peak; + + // + box.lower = provider + .decisionXConditions + .peaksGoldenBuffer[cIDX]; + + // + int lowerPeakIDX = -1; + double lowerPeak = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetLowerPeak( + lowerPeakIDX, + peak, + cBar.Index() // + ); + + // + int higherPeakIDX = -1; + double higherPeak = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetHigherPeak( + higherPeakIDX, + peak, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = + lowerPeakIDX < higherPeakIDX + ? lowerPeakIDX + : higherPeakIDX; + } + else if (IsValidIndex(lowerPeakIDX) && + !IsValidIndex(higherPeakIDX)) + { + // + fromIDX = lowerPeakIDX; + } + else if (!IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = higherPeakIDX; + } + } + + // + if (IsValidIndex(fromIDX)) + { + // + box.from = iTime( + zBar.symbol, + zBar.period, + fromIDX // + ); + } + else + { + box.from = pBar.time; + } + + // + signalProvider = X121SMC_XWZ_PROVIDER_ACTIVATED_BOX; + } + } diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_DJ30.spot_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_DJ30.spot_M5.x121.log.txt new file mode 100644 index 0000000..b34e4b4 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_DJ30.spot_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: true +eaForceOBBarType: false +eaForceFVGBarType: true +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: false +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: true +eaForceSarOnBothSide: true +eaForceSarHasBreakout: true +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: false +eaForceHasRSITrending: false +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: true +eaFilterBasedOnADX: false +eaForceHasADXTrending: true +eaForceHasADXCrossing: false +eaFilterBasedOnATR: false +eaForceHasATRTrending: true +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: true +eaForceHasTrendPlace: false +eaForceHasTrendChange: true +eaForceHasTrendTrending: true +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: false +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: false +eaFilterBasedOnSignalBar: true +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_EURUSDb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_EURUSDb_M5.x121.log.txt new file mode 100644 index 0000000..3090b4e --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_EURUSDb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: false +eaForceOBBarType: true +eaForceFVGBarType: false +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: false +eaValidateBlockEdgeBreakout: true +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: false +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: true +eaForceSarOnBothSide: false +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: true +eaForceHasRSITrending: true +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: false +eaFilterBasedOnADX: false +eaForceHasADXTrending: true +eaForceHasADXCrossing: false +eaFilterBasedOnATR: true +eaForceHasATRTrending: true +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: true +eaForceHasTrendPlace: false +eaForceHasTrendChange: true +eaForceHasTrendTrending: false +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: false +eaForceHasTrendDirOnBothSide: true +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: false +eaFilterBasedOnSignalBar: false +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_GBPUSDb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_GBPUSDb_M5.x121.log.txt new file mode 100644 index 0000000..da77ff0 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_GBPUSDb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: false +eaForceOBBarType: true +eaForceFVGBarType: true +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: false +eaFilterBasedOnPV: true +eaFilterBasedOnSar: true +eaForceSarSwitched: false +eaForceSarOnBothSide: true +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: false +eaFilterBasedOnRSI: false +eaForceHasRSITrending: false +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: true +eaFilterBasedOnADX: false +eaForceHasADXTrending: true +eaForceHasADXCrossing: false +eaFilterBasedOnATR: false +eaForceHasATRTrending: false +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: false +eaForceHasTrendDir: true +eaForceHasTrendPlace: true +eaForceHasTrendChange: true +eaForceHasTrendTrending: true +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: true +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: true +eaFilterBasedOnSignalBar: true +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_NZDUSDb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_NZDUSDb_M5.x121.log.txt new file mode 100644 index 0000000..3e7b695 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_NZDUSDb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: true +eaForceOBBarType: false +eaForceFVGBarType: false +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: false +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: true +eaForceSarOnBothSide: true +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: false +eaForceHasRSITrending: true +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: true +eaFilterBasedOnADX: false +eaForceHasADXTrending: true +eaForceHasADXCrossing: true +eaFilterBasedOnATR: true +eaForceHasATRTrending: false +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: false +eaForceHasTrendPlace: false +eaForceHasTrendChange: false +eaForceHasTrendTrending: true +eaForceHasTrendRejection: true +eaForceHasTrendLineInside: true +eaForceHasTrendDirOnBothSide: true +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: false +eaFilterBasedOnSignalBar: true +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCADb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCADb_M5.x121.log.txt new file mode 100644 index 0000000..c7124af --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCADb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: true +eaForceOBBarType: true +eaForceFVGBarType: false +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: false +eaFilterBasedOnPV: true +eaFilterBasedOnSar: false +eaForceSarSwitched: true +eaForceSarOnBothSide: true +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: true +eaForceHasRSITrending: false +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: false +eaFilterBasedOnADX: false +eaForceHasADXTrending: false +eaForceHasADXCrossing: false +eaFilterBasedOnATR: true +eaForceHasATRTrending: true +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: true +eaForceHasTrendPlace: true +eaForceHasTrendChange: true +eaForceHasTrendTrending: true +eaForceHasTrendRejection: true +eaForceHasTrendLineInside: false +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: true +eaFilterBasedOnVolume: true +eaFilterBasedOnSignalBar: true +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCHFb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCHFb_M5.x121.log.txt new file mode 100644 index 0000000..d6c7fc6 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCHFb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: false +eaForceOBBarType: false +eaForceFVGBarType: false +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: true +eaFilterBasedOnSar: false +eaForceSarSwitched: false +eaForceSarOnBothSide: false +eaForceSarHasBreakout: true +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: true +eaForceHasRSITrending: true +eaForceHasRSIVPattern: true +eaForceHasRSICrossing: false +eaFilterBasedOnADX: true +eaForceHasADXTrending: false +eaForceHasADXCrossing: false +eaFilterBasedOnATR: false +eaForceHasATRTrending: false +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: false +eaForceHasTrendDir: false +eaForceHasTrendPlace: false +eaForceHasTrendChange: true +eaForceHasTrendTrending: false +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: true +eaForceHasTrendDirOnBothSide: true +eaFilterBasedOnDelta: true +eaFilterBasedOnVolume: true +eaFilterBasedOnSignalBar: true +eaFilterBasedOnHKSignalBar: true diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDJPYb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDJPYb_M5.x121.log.txt new file mode 100644 index 0000000..ad96fe4 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDJPYb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: true +eaForceOBBarType: false +eaForceFVGBarType: false +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: false +eaValidateBlockEdgeBreakout: true +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: true +eaForceSarOnBothSide: true +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: false +eaForceHasRSITrending: true +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: false +eaFilterBasedOnADX: false +eaForceHasADXTrending: false +eaForceHasADXCrossing: false +eaFilterBasedOnATR: false +eaForceHasATRTrending: false +eaForceHasATRBreakout: true +eaFilterBasedOnTrend: false +eaForceHasTrendDir: false +eaForceHasTrendPlace: true +eaForceHasTrendChange: true +eaForceHasTrendTrending: true +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: true +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: false +eaFilterBasedOnSignalBar: true +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAGUSDb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAGUSDb_M5.x121.log.txt new file mode 100644 index 0000000..10cd061 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAGUSDb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: false +eaForceOBBarType: true +eaForceFVGBarType: true +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: false +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: true +eaForceSarOnBothSide: false +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: false +eaForceHasRSITrending: false +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: true +eaFilterBasedOnADX: true +eaForceHasADXTrending: true +eaForceHasADXCrossing: true +eaFilterBasedOnATR: false +eaForceHasATRTrending: true +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: false +eaForceHasTrendDir: true +eaForceHasTrendPlace: false +eaForceHasTrendChange: false +eaForceHasTrendTrending: false +eaForceHasTrendRejection: true +eaForceHasTrendLineInside: true +eaForceHasTrendDirOnBothSide: true +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: false +eaFilterBasedOnSignalBar: false +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAUUSDb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAUUSDb_M5.x121.log.txt new file mode 100644 index 0000000..7593994 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAUUSDb_M5.x121.log.txt @@ -0,0 +1,42 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: false +eaForceOBBarType: false +eaForceFVGBarType: true +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: true +eaFilterBasedOnSar: true +eaForceSarSwitched: false +eaForceSarOnBothSide: true +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: true +eaFilterBasedOnRSI: false +eaForceHasRSITrending: true +eaForceHasRSIVPattern: true +eaForceHasRSICrossing: false +eaFilterBasedOnADX: false +eaForceHasADXTrending: true +eaForceHasADXCrossing: true +eaFilterBasedOnATR: false +eaForceHasATRTrending: true +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: true +eaForceHasTrendPlace: true +eaForceHasTrendChange: true +eaForceHasTrendTrending: true +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: false +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: false +eaFilterBasedOnSignalBar: false +eaFilterBasedOnHKSignalBar: false diff --git a/BKPS/14040626/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt b/BKPS/14040626/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt new file mode 100644 index 0000000..e141480 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt @@ -0,0 +1,43 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: true +eaForceOBBarType: true +eaForceFVGBarType: true +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: false +eaForceSarOnBothSide: false +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: false +eaFilterBasedOnRSI: false +eaForceHasRSITrending: false +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: false +eaFilterBasedOnADX: false +eaForceHasADXTrending: false +eaForceHasADXCrossing: false +eaFilterBasedOnATR: false +eaForceHasATRTrending: false +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: true +eaForceHasTrendPlace: true +eaForceHasTrendChange: false +eaForceHasTrendTrending: false +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: false +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: true +eaFilterBasedOnSignalBar: false +eaFilterBasedOnHKSignalBar: false + diff --git a/BKPS/14040626/Documents/XCATBEAInputs/inputs.config.filepath.txt b/BKPS/14040626/Documents/XCATBEAInputs/inputs.config.filepath.txt new file mode 100644 index 0000000..34f0b61 --- /dev/null +++ b/BKPS/14040626/Documents/XCATBEAInputs/inputs.config.filepath.txt @@ -0,0 +1 @@ +X121XCATBEA\X121XCATBEA_XAUUSDb_M5.x121.log diff --git a/BKPS/14040626/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set b/BKPS/14040626/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set new file mode 100644 index 0000000..fff3ec2 Binary files /dev/null and b/BKPS/14040626/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set differ diff --git a/BKPS/14040626/Experts/x-saherelm.backtester.ea.mq5 b/BKPS/14040626/Experts/x-saherelm.backtester.ea.mq5 new file mode 100644 index 0000000..2c66bba --- /dev/null +++ b/BKPS/14040626/Experts/x-saherelm.backtester.ea.mq5 @@ -0,0 +1,413 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XBackTester +// Description: a Backtest Tools Strategy Tester +// +// 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 XBackTester" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" + +// +// Definitions ... + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = false; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCBackTesterEA(); + + // + // Symbol / Period ... + eaExpert.symbol = _Symbol; + eaExpert.period = _Period; + + // + // Common ... + eaExpert.eaMagicNumber = eaMagicNumber; + eaExpert.eaSlippage = eaSlippage; + eaExpert.eaLogSuffix = eaTag; + + // + // Alert ... + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Configure Other Requirements ... + // eaExpert.volume = 0; + // eaExpert.riskInPoint = 0; + // eaExpert.allowedTPSLStep = 0; + // eaExpert.riskToRewardRatio = 0; + // eaExpert.minAllowedRiskInPoint = 0; + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + Print(ShortName, ": Initialized Successfully ..."); + 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); +} + +// +// 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(); +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionModified( + ticket, + profit, + comment // + ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionPartialClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + eaExpert.HandleOnTradeStateChanged(state); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Experts/x-saherelm.rr.tools.mq5 b/BKPS/14040626/Experts/x-saherelm.rr.tools.mq5 new file mode 100644 index 0000000..37aa246 --- /dev/null +++ b/BKPS/14040626/Experts/x-saherelm.rr.tools.mq5 @@ -0,0 +1,431 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XRRToolsEA +// Description: a Template For Exper Advisors +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XRRToolsEA" +#property strict + +// +#define ShortName "XRRTools" + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-rm.panel.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Helpers/x-saherelm.x121.xcc.helper.mq5" +#include "../Helpers/x-saherelm.x121.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XCTrade *eaTrader; // Trader of Expert Adviser ... +XCRMPanel eaMainWindow; // Main Window ... +XCX121XCTHelper *eaCTHelper; // Bar Timer Indicator Helper class ... +XCX121XCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Apply Chart Event on Main Window ... + eaMainWindow.ChartEvent(id, lparam, dparam, sparam); +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + X121XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCTHelper = new XCX121XCTHelper(); + result = eaCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + X121XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XCX121XCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCTHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // Initialize Application Main Window ... + result = eaMainWindow.Create( + ChartID(), + ShortName, // Dialog Name ... + 0, // SubWindow ... + 10, // X1 ... + 35, // Y1 ... + 300, // X2 ... + 200 // Y2 ... + ); + + // + // Try To Run Main Window ... + if (result) + { + eaMainWindow.Run(); + } + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + eaMainWindow.UpdateState(); +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + eaMainWindow.Destroy(); +} + +// diff --git a/BKPS/14040626/Experts/x-saherelm.x121.xcatb.ea.mq5 b/BKPS/14040626/Experts/x-saherelm.x121.xcatb.ea.mq5 new file mode 100644 index 0000000..dbcdd4e --- /dev/null +++ b/BKPS/14040626/Experts/x-saherelm.x121.xcatb.ea.mq5 @@ -0,0 +1,635 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121XCATB +// Description: X121XCATB base Expert Advisor ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121XCATB based Expert Advisor" +#property strict + +// +#define ShortName "X121XCATBEA" + +// +// Importts ... +#include "../XCATBEA/Classes/xcatbea.expert.class.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 1694056; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Detector ... +input group "Detector"; + +// +// Validating ... +input group "Validations"; +input bool eaForceHasSwing = false; // Force Block to Has Propper Swing +input bool eaForceOBBarType = false; // Force Order Block to Has InDirectional Bars +input int eaMinRequiredOBBar = 0; // Min Required OB Bar +input bool eaForceFVGBarType = false; // Force Fair Value Gaps Bars Type +input int eaLiquidityLoopback = 0; // Liquidity Detection Loopback +input double eaMaxAllowedRange = 0.0; // Max Allowed Order Block Range +input double eaMinAllowedRange = 0.0; // Min Allowed Order Block Range +input bool eaForceHasFLiquidity = false; // Force Order Block To Has Reversal Liquidity +input bool eaForceHasRLiquidity = false; // Force Order Block to Has Following Liquidity +input bool eaValidateGapSequence = false; // Validate Fair Value Gaps Bar Sequences +input int eaMinAllowedBlockLength = 0; // Min Allowed Block Length +input bool eaValidateBlockEdgeBreakout = false; // Validate Order Block Edge Breakeout + +// +// Filtering ... +input group "Filters"; +input bool eaFilterBasedOnKI = false; // Filter Based On KI Flats +input bool eaFilterBasedOnPV = false; // Filter Based On PV +input int eaBosLoopback = 0; // PV Based Filtering BOS Lookup +input bool eaFilterBasedOnSar = false; // Filter Based On SAR +input bool eaForceSarSwitched = false; // SAR Switched on Sides for Filtering +input bool eaForceSarOnBothSide = false; // SAR Check on Both Sides for Filtering +input bool eaForceSarHasBreakout = false; // SAR Must Breakout +input bool eaForceSarHasReversalSide = false; // SAR Must Has Reversal Direction +input bool eaFilterBasedOnRSI = false; // Filter Based On RSI +input bool eaForceHasRSITrending = false; // RSI Must Has Trending +input bool eaForceHasRSIVPattern = false; // RSI Must Has V Pattern +input bool eaForceHasRSICrossing = false; // RSI Must Has Crossing Levels +input bool eaFilterBasedOnADX = false; // Filter Based On ADX +input bool eaForceHasADXTrending = false; // ADX Must Has Trending +input bool eaForceHasADXCrossing = false; // ADX Must Has Crossing +DI/-DI +input bool eaFilterBasedOnATR = false; // Filter Based On ATR +input bool eaForceHasATRTrending = false; // ATR Must Has Trending +input bool eaForceHasATRBreakout = false; // ATR Must Has Breakout +input bool eaFilterBasedOnTrend = false; // Filter Based On Trend +input bool eaForceHasTrendDir = false; // TREND Must Has Following Direction +input bool eaForceHasTrendPlace = false; // TREND Place Based Filtering +input bool eaForceHasTrendChange = false; // TREND Change Filtering +input bool eaForceHasTrendTrending = false; // TREND Must Has Trending +input bool eaForceHasTrendRejection = false; // TREND Line Must Rejected +input bool eaForceHasTrendLineInside = false; // TREND Line has Inside +input bool eaForceHasTrendDirOnBothSide = false; // TREND Must Has Following Direction in Both Side +input bool eaFilterBasedOnDelta = false; // Filter Based On Delta +input bool eaFilterBasedOnVolume = false; // Filter Based On Volume +input bool eaFilterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool eaFilterBasedOnHKSignalBar = false; // Filter Based On HK Signal Bar + +// +// Signal ... +input group "Signal"; +input int eaSignalR2R = 2; // Risk Reward Ratio +input double eaSLATRMultiplier = 0; // ATR Multiplier for SL +input bool eaAllowSignallingBasedOnConditions = false; // Signalling Based on Market Conditions +input bool eaAllowSignallingBasedOnTriggerBlocks = false; // Signalling Based on Trigger Blocks +input bool eaAllowSignallingBasedOnTriggerBlocksInsideOther = false; // Signalling Based on Trigger Blocks Seccond inputs +input bool eaSecondsTriggersSLUsingFirstTriggerBlock = true; // Use First Trigger Block for SL of Seconds Trigger Block Signalss +input bool eaApplyValidateAndFilterOnSelectInsideOthers = false; // Select Trigger Blocks by Applying Validations and Filterss +input bool eaAllowSignallingConditions1 = true; // Allow Market Conditions Signaller to Using Sar Signals +input bool eaAllowSignallingConditions2 = true; // Allow Market Conditions Signaller to Using Trend Signals +input bool eaAllowSignallingConditions3 = true; // Allow Market Conditions Signaller to Using Delta Signals +input bool eaAllowSignallingConditions4 = true; // Allow Market Conditions Signaller to Using Volume Signals +input bool eaAllowSignallingConditions5 = true; // Allow Market Conditions Signaller to Using Signal Bar Signals +input bool eaAllowSignallingConditions6 = true; // Allow Market Conditions Signaller to Using HK Signal Bar Signals + +// +// Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_EQUITY; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 0.5; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 0.0; // Constant Balance for Calculations + +// +// Management ... +// eaSymbols => comma separated Symbols for Trading, use Default if not Provided ... +// eaSessions => (ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00) +input group "Management"; +input string eaSymbols = ""; // Allowed Trading Symbols +input bool eaAllowGuards = false; // Allow Guards +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input string eaSessions = ""; // Active Sessions +input ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; // Restrictions Period +input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period +input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period +input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period +input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades +input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade +input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade +input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaSaveAlerts = true; // Save Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = true; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = true; // Report New Days +input bool eaReportNewHours = false; // Report New Hours +input bool eaReportTrades = true; // Report Trades +input bool eaReportSignals = true; // Report Signals +input bool eaReportRestrictions = true; // Report Restrictions +input bool eaReportProtector = true; // Report Protector Actions +input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished + +// +// Collector ... +input group "Collector"; +input bool eaSaveTrades = true; // Save Trades +input bool eaSaveSignals = true; // Save Signals +input bool eaSaveWins = true; // Save Winning Conditions +input bool eaSaveLosts = true; // Save Lost Conditions +input bool eaSaveRestrictions = true; // Save Restriction Reports + +// +// Variables ... + +// +XCXCATBEAExpert *eaExpert; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCXCATBEAExpert(); + + // + // Setting All Inputs to Expert Adviser Class ... + + // + // Common ... + eaExpert.eaLogSuffix = eaTag; + eaExpert.eaSlippage = eaSlippage; + eaExpert.eaMagicNumber = eaMagicNumber; + + // + // Detector ... + + // + // Validations ... + eaExpert.eaForceHasSwing = eaForceHasSwing; + eaExpert.eaForceOBBarType = eaForceOBBarType; + eaExpert.eaForceFVGBarType = eaForceFVGBarType; + eaExpert.eaMaxAllowedRange = eaMaxAllowedRange; + eaExpert.eaMinAllowedRange = eaMinAllowedRange; + eaExpert.eaMinRequiredOBBar = eaMinRequiredOBBar; + eaExpert.eaLiquidityLoopback = eaLiquidityLoopback; + eaExpert.eaForceHasFLiquidity = eaForceHasFLiquidity; + eaExpert.eaForceHasRLiquidity = eaForceHasRLiquidity; + eaExpert.eaValidateGapSequence = eaValidateGapSequence; + eaExpert.eaMinAllowedBlockLength = eaMinAllowedBlockLength; + eaExpert.eaValidateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Filters ... + eaExpert.eaBosLoopback = eaBosLoopback; + eaExpert.eaFilterBasedOnKI = eaFilterBasedOnKI; + eaExpert.eaFilterBasedOnPV = eaFilterBasedOnPV; + eaExpert.eaFilterBasedOnSar = eaFilterBasedOnSar; + eaExpert.eaFilterBasedOnRSI = eaFilterBasedOnRSI; + eaExpert.eaForceSarSwitched = eaForceSarSwitched; + eaExpert.eaFilterBasedOnADX = eaFilterBasedOnADX; + eaExpert.eaFilterBasedOnATR = eaFilterBasedOnATR; + eaExpert.eaForceHasTrendDir = eaForceHasTrendDir; + eaExpert.eaForceSarOnBothSide = eaForceSarOnBothSide; + eaExpert.eaFilterBasedOnTrend = eaFilterBasedOnTrend; + eaExpert.eaForceHasTrendPlace = eaForceHasTrendPlace; + eaExpert.eaFilterBasedOnDelta = eaFilterBasedOnDelta; + eaExpert.eaForceSarHasBreakout = eaForceSarHasBreakout; + eaExpert.eaForceHasRSITrending = eaForceHasRSITrending; + eaExpert.eaForceHasRSIVPattern = eaForceHasRSIVPattern; + eaExpert.eaForceHasRSICrossing = eaForceHasRSICrossing; + eaExpert.eaForceHasADXTrending = eaForceHasADXTrending; + eaExpert.eaForceHasADXCrossing = eaForceHasADXCrossing; + eaExpert.eaForceHasATRTrending = eaForceHasATRTrending; + eaExpert.eaForceHasATRBreakout = eaForceHasATRBreakout; + eaExpert.eaForceHasTrendChange = eaForceHasTrendChange; + eaExpert.eaFilterBasedOnVolume = eaFilterBasedOnVolume; + eaExpert.eaForceHasTrendTrending = eaForceHasTrendTrending; + eaExpert.eaForceHasTrendRejection = eaForceHasTrendRejection; + eaExpert.eaFilterBasedOnSignalBar = eaFilterBasedOnSignalBar; + eaExpert.eaForceSarHasReversalSide = eaForceSarHasReversalSide; + eaExpert.eaForceHasTrendLineInside = eaForceHasTrendLineInside; + eaExpert.eaFilterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + eaExpert.eaForceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + // Signal ... + eaExpert.eaSignalR2R = eaSignalR2R; + eaExpert.eaSLATRMultiplier = eaSLATRMultiplier; + eaExpert.eaAllowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + eaExpert.eaAllowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + eaExpert.eaSecondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + eaExpert.eaApplyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + eaExpert.eaAllowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + eaExpert.eaAllowSignallingConditions1 = eaAllowSignallingConditions1; + eaExpert.eaAllowSignallingConditions2 = eaAllowSignallingConditions2; + eaExpert.eaAllowSignallingConditions3 = eaAllowSignallingConditions3; + eaExpert.eaAllowSignallingConditions4 = eaAllowSignallingConditions4; + eaExpert.eaAllowSignallingConditions5 = eaAllowSignallingConditions5; + eaExpert.eaAllowSignallingConditions6 = eaAllowSignallingConditions6; + + // + // Volume ... + eaExpert.eaVolumeSelect = eaVolumeSelect; + eaExpert.eaStaticVoluem = eaStaticVoluem; + eaExpert.eaConstantPercent = eaConstantPercent; + eaExpert.eaConstantBalance = eaConstantBalance; + eaExpert.eaConstantRiskBalance = eaConstantRiskBalance; + eaExpert.eaDynamicVolumeStepVolume = eaDynamicVolumeStepVolume; + eaExpert.eaDynamicVolumeStepBalance = eaDynamicVolumeStepBalance; + + // + // Management ... + eaExpert.eaSymbols = eaSymbols; + eaExpert.eaSessions = eaSessions; + eaExpert.eaAllowTrade = eaAllowTrade; + eaExpert.eaAllowLongs = eaAllowLongs; + eaExpert.eaAllowGuards = eaAllowGuards; + eaExpert.eaAllowShorts = eaAllowShorts; + eaExpert.eaMaxAllowedTPs = eaMaxAllowedTPs; + eaExpert.eaMaxAllowedSLs = eaMaxAllowedSLs; + eaExpert.eaMaxAllowedTrades = eaMaxAllowedTrades; + eaExpert.eaMaxAllowedSpread = eaMaxAllowedSpread; + eaExpert.eaRestrictionsPeriod = eaRestrictionsPeriod; + eaExpert.eaMaxAllowedPositions = eaMaxAllowedPositions; + eaExpert.eaCloseAllOpenTradesAt = eaCloseAllOpenTradesAt; + eaExpert.eaMaxAllowedDrawdownFactor = eaMaxAllowedDrawdownFactor; + + // + // Alert ... + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaSaveAlerts = eaSaveAlerts; + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Reports ... + eaExpert.eaReportTrades = eaReportTrades; + eaExpert.eaReportNewDays = eaReportNewDays; + eaExpert.eaReportSignals = eaReportSignals; + eaExpert.eaReportNewWeeks = eaReportNewWeeks; + eaExpert.eaReportNewHours = eaReportNewHours; + eaExpert.eaReportProtector = eaReportProtector; + eaExpert.eaReportNewMonths = eaReportNewMonths; + eaExpert.eaReportRestrictions = eaReportRestrictions; + eaExpert.eaReportAfterTradesBalance = eaReportAfterTradesBalance; + + // + // Collector ... + eaExpert.eaSaveWins = eaSaveWins; + eaExpert.eaSaveLosts = eaSaveLosts; + eaExpert.eaSaveTrades = eaSaveTrades; + eaExpert.eaSaveSignals = eaSaveSignals; + eaExpert.eaSaveRestrictions = eaSaveRestrictions; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + return INIT_FAILED; + } + + // + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + eaExpert.HandleOnDeInit(); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); +} + +// +// Event Listeners ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionModified( + ticket, + profit, + comment // + ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionPartialClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + eaExpert.HandleOnTradeStateChanged(state); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Experts/x-saherelm.xfima.backtester.ea.mq5 b/BKPS/14040626/Experts/x-saherelm.xfima.backtester.ea.mq5 new file mode 100644 index 0000000..46b4355 --- /dev/null +++ b/BKPS/14040626/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -0,0 +1,1027 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XBackTester +// Description: a Backtest Tools Strategy Tester +// +// 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 XBackTester" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Helpers/x-saherelm.xom1.helper.mq5" + +// +// Definitions ... + +// +// 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 + +// +// Indicator Inputs ... +// +input group "Calculation"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// PV ... +input ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +input ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method + +// +// Others ... +input ENUM_X_FIBO_LEVELS upperZoneLevel = X_FIBO_LEVEL_618; // Upper Zone Level +input ENUM_X_FIBO_LEVELS lowerZoneLevel = X_FIBO_LEVEL_382; // Lower Zone Level +input double sarStep = 0.02; // SAR Step +input double sarMax = 0.2; // SAR Maximum +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To +input int maFastLength = 7; // Fast MA Length +input int maSlowLength = 20; // Slow MA Length + +// +input group "Bar Timer"; +input int barTimeFontSize = 10; // Font Size +input string barTimeFont = "Arial"; // Font +input color barTimeColor = clrYellow; // Text Color +input ENUM_BASE_CORNER barTimeCorner = CORNER_RIGHT_LOWER; // Text Position + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showBarTime = true; // Show Bar Time +input bool showFiboZone = false; // Show Fibo Zone + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +input int sarArrowCode = 159; // Parabolic Sar Arrow Code +input int peakArrowCode = 159; // Peaks Arrow Code +input int valeArrowCode = 159; // Vales Arrow Code + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... +XCMarketPatternDetector *eaPatternDetector; // EA Pattern Detector ... + +// +XCPOIDrawer *eaDrawer; // Ea POI Drawer ... +CArrayObj draws; // Drawn Objects ... + +// +XBarTracker eaBarTracker; // EA Bar Traker ... + +// +int eaHandler = INVALID_HANDLE; // Indicator Handler ... +int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... + +// +ENUM_X_DIRECTION trendDir = X_DIRECTION_NONE; + +// +// Define Indicators Here ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCBackTesterEA(); + + // + // Symbol / Period ... + eaExpert.symbol = _Symbol; + eaExpert.period = _Period; + + // + // Common ... + eaExpert.eaMagicNumber = eaMagicNumber; + eaExpert.eaSlippage = eaSlippage; + eaExpert.eaLogSuffix = eaTag; + + // + // Alert ... + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Configure Other Requirements ... + eaExpert.volume = 0.01; + eaExpert.riskInPoint = 200; + eaExpert.allowedTPSLStep = 10; + eaExpert.riskToRewardRatio = 2; + eaExpert.minAllowedRiskInPoint = 20; + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Initial Indicator Handler ... + eaHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xom1", + "", // Calculation ... + scMethod, + scPeriod, + mcMethod, + mcPeriod, + lcMethod, + lcPeriod, + hcMethod, + hcPeriod, + upperMode, + lowerMode, + upperZoneLevel, + lowerZoneLevel, + sarStep, + sarMax, + maMethod, + maAppliedTo, + maFastLength, + maSlowLength, + "", // Presentation ... + showPV, + showSAR, + showMAFast, + showMASlow, + showFiboZone, + startCalculationForLastBars, + sarArrowCode, + peakArrowCode, + valeArrowCode + // + ); + isInited = eaHandler != INVALID_HANDLE; + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Initialize Candle Timer Handler ... + eaCTHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xct", + // + // Inputs ... + barTimeFontSize, // Font Size ... + barTimeFont, // Font ... + barTimeColor, // Text Color ... + barTimeCorner, // Text Position ... + // + // Presentation ... + "", + showBarTime // Show Candle Time + // + ); + isInited = eaCTHandler != INVALID_HANDLE; + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Initialize Bar Tracker ... + isInited = eaBarTracker.Init( + _Symbol, + _Period // + ); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Instantiate Market Pattern Detector ... + eaPatternDetector = new XCMarketPatternDetector(); + + // + // Instantiate POI Drawer ... + eaDrawer = new XCPOIDrawer(); + + // + Print(ShortName, ": Initialized Successfully ..."); + 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(); + + // + // De Init Indicator ... + IndicatorRelease(eaHandler); + + // + eaBarTracker.Clean(); + + // + delete eaDrawer; + ZeroMemory(eaDrawer); + + // + delete eaPatternDetector; + ZeroMemory(eaPatternDetector); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + eaExpert.HandleOnTick(); + + // + DetectPatterns(); +} + +// +// 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); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 && + // + // Indicator Inputs ... + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ); + 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(); +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionModified( + ticket, + profit, + comment // + ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionPartialClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + eaExpert.HandleOnTradeStateChanged(state); +} + +/** + * Check Market Conditions for Pattern Detection ... + */ +void DetectPatterns() +{ + // + bool isNewBar = eaBarTracker.IsNewBar(); + if (!isNewBar) + { + return; + } + + // + // Initialize 1 Indexed Bar ... + XOHCL cBar; + bool has = cBar.Init( + _Symbol, + _Period, + 1 // + ); + if (!has) + { + return; + } + + // + // Do Analysis ... + + // + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Define Detection Flags ... + + // + bool detectPinned = false; + bool detectMomentum = false; + bool detectEngulfed = false; + bool detectTrueGaped = false; + + // + bool detectStarPattern = false; + bool detectFlagPattern = false; + bool detectRisingPattern = false; + bool detectPiercingPattern = false; + bool detectSignalKeyBarPattern = false; + + // + bool detectSwingTrend = false; + bool detectSwingTrendBreakes = false; + + // + bool detectSupports = false; + bool detectResistance = false; + + // + // Checking Momentum Bar ... + if (detectMomentum) + { + // + bool isMomentum = eaPatternDetector.IsMomentumBar( + cBar, + iDir // + ); + bool isBullishMomentum = isMomentum && + IsSpecifiedBullish(iDir); + bool isBearishMomentum = isMomentum && + IsSpecifiedBearish(iDir); + if (isMomentum) + { + Print(ToXString(iDir), " Momentum Bar: ", cBar.time); + } + } + + // + // Checking Engulfed Bar ... + if (detectEngulfed) + { + // + bool isEngulfed = eaPatternDetector.IsEngulfedBar( + cBar, + iDir // + ); + bool isBullishEngulfed = isEngulfed && + IsSpecifiedBullish(iDir); + bool isBearishEngulfed = isEngulfed && + IsSpecifiedBearish(iDir); + if (isEngulfed) + { + Print(ToXString(iDir), " Engulfed Bar: ", cBar.time); + } + } + + // + // Checking TruGaped Bar ... + if (detectTrueGaped) + { + // + bool isTrueGaped = eaPatternDetector.IsTrueGapedBar( + cBar, + iDir // + ); + bool isBullishTrueGaped = isTrueGaped && + IsSpecifiedBullish(iDir); + bool isBearishTrueGaped = isTrueGaped && + IsSpecifiedBearish(iDir); + if (isTrueGaped) + { + Print(ToXString(iDir), " TrueGapped Bar: ", cBar.time); + } + } + + // + // Checking Pinned Bar ... + if (detectPinned) + { + bool isPinned = eaPatternDetector.IsPinnedBar( + cBar, + iDir // + ); + bool isBullishPinned = isPinned && + IsSpecifiedBullish(iDir); + bool isBearishPinned = isPinned && + IsSpecifiedBearish(iDir); + if (isPinned) + { + Print(ToXString(iDir), " Pinned Bar: ", cBar.time); + } + } + + // + // Checking Star Pattern ... + if (detectStarPattern) + { + bool isStarPattern = eaPatternDetector.IsStartPattern( + cBar, + iDir // + ); + bool isBullishStarPattern = isStarPattern && + IsSpecifiedBullish(iDir); + bool isBearishStarPattern = isStarPattern && + IsSpecifiedBearish(iDir); + if (isStarPattern) + { + Print(ToXString(iDir), " Star Pattern: ", cBar.time); + } + } + + // + // Checking Piercing Pattern ... + if (detectPiercingPattern) + { + // + bool isPiercingPattern = eaPatternDetector.IsPiercingPattern( + cBar, + iDir // + ); + bool isBullishPiercingPattern = isPiercingPattern && + IsSpecifiedBullish(iDir); + bool isBearishPiercingPattern = isPiercingPattern && + IsSpecifiedBearish(iDir); + if (isPiercingPattern) + { + Print(ToXString(iDir), " Piercing Pattern: ", cBar.time); + } + } + + // + // Checking Rising Pattern ... + if (detectRisingPattern) + { + // + bool isRisingPattern = eaPatternDetector.IsRisingPattern( + cBar, + iDir // + ); + bool isBullishRisingPattern = isRisingPattern && + IsSpecifiedBullish(iDir); + bool isBearishRisingPattern = isRisingPattern && + IsSpecifiedBearish(iDir); + if (isRisingPattern) + { + Print(ToXString(iDir), " Rising Pattern: ", cBar.time); + } + } + + // + // Checking Flag Pattern ... + if (detectFlagPattern) + { + // + XOHCL swingBar; + bool isFlagPattern = eaPatternDetector.IsFlagPattern( + cBar, + iDir, + swingBar // + ); + bool isBullishFlagPattern = isFlagPattern && + IsSpecifiedBullish(iDir); + bool isBearishFlagPattern = isFlagPattern && + IsSpecifiedBearish(iDir); + if (isFlagPattern) + { + Print(ToXString(iDir), " Flag Pattern: ", cBar.time, ", Swing: ", swingBar.time); + } + swingBar.Clean(); + } + + // + // Detect SignalKey Bar Pattern ... + if (detectSignalKeyBarPattern) + { + // + bool isSignalKeyBar = eaPatternDetector.IsSignalKeyBarPattern( + cBar, + iDir // + ); + bool isBullishSignalKeyBar = isSignalKeyBar && + IsSpecifiedBullish(iDir); + bool isBearishSignalKeyBar = isSignalKeyBar && + IsSpecifiedBearish(iDir); + if (isSignalKeyBar) + { + Print(ToXString(iDir), " SignalKey Bar Pattern: ", cBar.time); + } + } + + // + // Detect Swing Trend ... + if (detectSwingTrend) + { + // + XOHCL swings[]; + bool hasSwingTrend = eaPatternDetector.HasSwingTrend( + cBar, + iDir, + swings // + ); + bool hasBullishSwingTrend = hasSwingTrend && + IsSpecifiedBullish(iDir); + bool hasBearishSwingTrend = hasSwingTrend && + IsSpecifiedBearish(iDir); + if (hasSwingTrend) + { + // + Print(ToXString(iDir), " Swing Trend: ", cBar.time); + + // + CChartObjectTrend *iObj; + has = eaDrawer.DrawSwingTrend( + swings, + iDir, + iObj, + true // Ray Right ... + ); + if (has) + { + draws.Add(iObj); + } + } + SpecifiedClean(swings); + } + + // + // Swing Trend Breakes ... + if (detectSwingTrendBreakes) + { + // + XOHCL swings[]; + bool hasSwingTrend = eaPatternDetector.HasSwingTrend( + cBar, + iDir, + swings // + ); + bool hasBullishSwingTrend = hasSwingTrend && + IsSpecifiedBullish(iDir); + bool hasBearishSwingTrend = hasSwingTrend && + IsSpecifiedBearish(iDir); + if (hasSwingTrend) + { + // + if (!HasDirection(trendDir)) + { + trendDir = iDir; + } + } + + // + // Breaked Detection ... + if (trendDir != iDir) + { + // + Print("Trend Dir Breaked to: ", ToXString(iDir)); + trendDir = iDir; + } + + // + SpecifiedClean(swings); + } + + // + // Detect Supports ... + if (detectSupports) + { + // + XOHCL support; + bool hasSupport = eaPatternDetector.HasSupport( + cBar, + support // + ); + if (hasSupport) + { + // + XBoxZone supportBox; + has = ToSupportBox(support, supportBox); + if (has) + { + // + // Draw Box ... + XCBoxObject *iObj; + has = eaDrawer.DrawBox( + supportBox, + iObj // + ); + if (has) + { + // + // Apply Style ... + eaDrawer.ApplyStyle( + iObj, + eaDrawer.boxBullishStyle // + ); + + // + draws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + supportBox.Clean(); + } + support.Clean(); + } + + // + // Detect Resistance ... + if (detectResistance) + { + // + XOHCL resistance; + bool hasResistance = eaPatternDetector.HasResistance( + cBar, + resistance // + ); + if (hasResistance) + { + // + XBoxZone resistanceBox; + has = ToResistanceBox(resistance, resistanceBox); + if (has) + { + // + // Draw Box ... + XCBoxObject *iObj; + has = eaDrawer.DrawBox( + resistanceBox, + iObj // + ); + if (has) + { + // + // Apply Style ... + eaDrawer.ApplyStyle( + iObj, + eaDrawer.boxBearishStyle // + ); + + // + draws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + resistanceBox.Clean(); + } + resistance.Clean(); + } + + // + cBar.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Experts/x-saherelm.xom1.ea.mq5 b/BKPS/14040626/Experts/x-saherelm.xom1.ea.mq5 new file mode 100644 index 0000000..473dbab --- /dev/null +++ b/BKPS/14040626/Experts/x-saherelm.xom1.ea.mq5 @@ -0,0 +1,565 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XOM1 +// Description: XOM1 base Expert Advisor ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XOM1 based Expert Advisor" +#property strict + +// +#define ShortName "XOM1EA" + +// +// Importts ... +#include "../XOM1EA/Classes/xom1ea.expert.class.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 1694056; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Symbols +// [ +// Symbol| +// period| +// (ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00)| +// maxAllowedSpread| +// maxAllowedPosition| +// ( +// restrictionsPeriod, +// restrictionsMultiplier, +// maxAllowedTPs, +// maxAllowedSLs, +// maxAllowedTrades, +// closeAllOpenTradesAt +// ) +// ] +// +// +// [XAUUSDb|M5|(ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00)|25.0|5|(XTRADE_RESTRICATION_DAILY,1,0,2,0)] +input string eaSymbolConfiguration = "[XAUUSDb|M5|(ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00)|25.0|5|(XTRADE_RESTRICATION_DAILY,3,0,2,0)]"; // Symbol Configurations + +// +// Management ... +input group "Management"; +input bool eaAllowGuards = false; // Allow Guards +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade + +// +// Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_CONSTANT; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 1; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 1000.0; // Constant Balance for Calculations + +// +// Alert ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaSaveAlerts = true; // Save Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = true; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Reports ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = true; // Report New Days +input bool eaReportNewHours = false; // Report New Hours +input bool eaReportTrades = true; // Report Trades +input bool eaReportSignals = true; // Report Signals +input bool eaReportRestrictions = true; // Report Restrictions +input bool eaReportProtector = true; // Report Protector Actions +input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished + +// +// Collector ... +input group "Collector"; +input bool eaSaveTrades = true; // Save Trades +input bool eaSaveSignals = true; // Save Signals +input bool eaSaveWins = true; // Save Winning Conditions +input bool eaSaveLosts = true; // Save Lost Conditions +input bool eaSaveRestrictions = true; // Save Restriction Reports + +// +// Variables ... + +// +XCXOM1EAExpert *eaExpert; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters ... + + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCXOM1EAExpert(); + + // + // Setting All Inputs to Expert Adviser Class ... + + // + // Common ... + eaExpert.eaMagicNumber = eaMagicNumber; + eaExpert.eaSlippage = eaSlippage; + eaExpert.eaLogSuffix = eaTag; + + // + // Symbols ... + eaExpert.eaSymbolConfiguration = eaSymbolConfiguration; + + // + // Management ... + eaExpert.eaAllowGuards = eaAllowGuards; + eaExpert.eaAllowTrade = eaAllowTrade; + eaExpert.eaAllowLongs = eaAllowLongs; + eaExpert.eaAllowShorts = eaAllowShorts; + eaExpert.eaMaxAllowedDrawdownFactor = eaMaxAllowedDrawdownFactor; + + // + // Volume ... + eaExpert.eaVolumeSelect = eaVolumeSelect; + eaExpert.eaStaticVoluem = eaStaticVoluem; + eaExpert.eaDynamicVolumeStepBalance = eaDynamicVolumeStepBalance; + eaExpert.eaDynamicVolumeStepVolume = eaDynamicVolumeStepVolume; + eaExpert.eaConstantRiskBalance = eaConstantRiskBalance; + eaExpert.eaConstantPercent = eaConstantPercent; + eaExpert.eaConstantBalance = eaConstantBalance; + + // + // Alert ... + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaSaveAlerts = eaSaveAlerts; + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Reports ... + eaExpert.eaReportNewMonths = eaReportNewMonths; + eaExpert.eaReportNewWeeks = eaReportNewWeeks; + eaExpert.eaReportNewDays = eaReportNewDays; + eaExpert.eaReportNewHours = eaReportNewHours; + eaExpert.eaReportTrades = eaReportTrades; + eaExpert.eaReportSignals = eaReportSignals; + eaExpert.eaReportRestrictions = eaReportRestrictions; + eaExpert.eaReportProtector = eaReportProtector; + eaExpert.eaReportAfterTradesBalance = eaReportAfterTradesBalance; + + // + // Collector ... + eaExpert.eaSaveTrades = eaSaveTrades; + eaExpert.eaSaveSignals = eaSaveSignals; + eaExpert.eaSaveWins = eaSaveWins; + eaExpert.eaSaveLosts = eaSaveLosts; + eaExpert.eaSaveRestrictions = eaSaveRestrictions; + + // + // Attach Event Handlers ... + eaExpert.AddOnSignalEventHandler(OnSignalTriggered); + eaExpert.onGuardedEventHandler = OnGuardedTriggered; + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.canAnalyseEventHandler = CanAnalyseEventTriggered; + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.checkForGuardEventHandler = CheckForGuardTriggered; + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + Print(ShortName, ": Initialized Successfully ..."); + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + eaExpert.HandleOnDeInit(); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); +} + +// +// Event Listeners ... + +/** + * Handle CanAnalyse Event Triggered ... + * + * @param symbol: Symbol ... + * @param period: Period ... + * @param time: Analysing Time ... + * + * @return ( bool ) + */ +bool CanAnalyseEventTriggered( + string symbol, + ENUM_TIMEFRAMES period, + datetime time // +) +{ + return eaExpert.HandleCanAnalyseEventTriggered( + symbol, + period, + time // + ); +} + +/** + * Check For Guard Event Handler ... + * + * @param guards: XGuard[] + * + * @return ( int ) + */ +int CheckForGuardTriggered(XGuard &guards[]) { + return eaExpert.CheckForGuardTriggered(guards); +} + +/** + * Handle Guard Events ... + * + * @param action: ENUM_X_GUARD_ACTIONS + * @param positions: XPosition[] + */ +void OnGuardedTriggered( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // +) +{ + eaExpert.OnGuardedTriggered(action, positions); +} + +/** + * Trigger OnSignal Event ... + * + * @param signal: XSignal + */ +void OnSignalTriggered(XSignal &signal) +{ + eaExpert.HandleOnSignalTriggered(signal); +} + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionModified( + ticket, + profit, + comment // + ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionPartialClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + eaExpert.HandleOnTradeStateChanged(state); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} diff --git a/BKPS/14040626/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/BKPS/14040626/Helpers/x-saherelm.x121.xcatb.helper.mq5 new file mode 100644 index 0000000..c0b833b --- /dev/null +++ b/BKPS/14040626/Helpers/x-saherelm.x121.xcatb.helper.mq5 @@ -0,0 +1,6693 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCatbHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_XCATB_BUFFERS +{ + X121_XCATB_SAR_LINE = 0, + X121_XCATB_SAR_COLOR_LINE = 1, + X121_XCATB_PEAK_LINE = 2, + X121_XCATB_VALE_LINE = 3, + X121_XCATB_PEAK_GOLDEN_LINE = 4, + X121_XCATB_VALE_GOLDEN_LINE = 5, + X121_XCATB_ATR_BAND_UPPER_LINE = 6, + X121_XCATB_ATR_BAND_LOWER_LINE = 7, + X121_XCATB_TREND_LINE = 8, + X121_XCATB_TREND_COLOR_LINE = 9, + X121_XCATB_SBAR_O_LINE = 10, + X121_XCATB_SBAR_H_LINE = 11, + X121_XCATB_SBAR_L_LINE = 12, + X121_XCATB_SBAR_C_LINE = 13, + X121_XCATB_SBAR_COLOR_LINE = 14, + X121_XCATB_HK_SBAR_O_LINE = 15, + X121_XCATB_HK_SBAR_H_LINE = 16, + X121_XCATB_HK_SBAR_L_LINE = 17, + X121_XCATB_HK_SBAR_C_LINE = 18, + X121_XCATB_HK_SBAR_COLOR_LINE = 19, + X121_XCATB_S_HH_LINE = 20, + X121_XCATB_S_LL_LINE = 21, + X121_XCATB_M_HH_LINE = 22, + X121_XCATB_M_LL_LINE = 23, + X121_XCATB_L_HH_LINE = 24, + X121_XCATB_L_LL_LINE = 25, + X121_XCATB_H_HH_LINE = 26, + X121_XCATB_H_LL_LINE = 27, + X121_XCATB_KI_LINE = 28, + X121_XCATB_KI_COLOR_LINE = 29, + X121_XCATB_SAR_STATE_LINE = 30, + X121_XCATB_TREND_STATE_LINE = 31, + X121_XCATB_RSI_LINE = 32, + X121_XCATB_ADX_LINE = 33, + X121_XCATB_ADXP_LINE = 34, + X121_XCATB_ADXN_LINE = 35, + X121_XCATB_DELTA_LINE = 36, + X121_XCATB_DELTA_SIGNAL_LINE = 37, + X121_XCATB_VOLUME_BULLISH_LINE = 38, + X121_XCATB_VOLUME_BEARISH_LINE = 39, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE = 40, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE = 41, + X121_XCATB_ATR_LINE = 42, + X121_XCATB_ATR_BAND_RAW_UPPER_LINE = 43, + X121_XCATB_ATR_BAND_RAW_LOWER_LINE = 44, + X121_XCATB_HK_BAR_O_LINE = 45, + X121_XCATB_HK_BAR_H_LINE = 46, + X121_XCATB_HK_BAR_L_LINE = 47, + X121_XCATB_HK_BAR_C_LINE = 48, + X121_XCATB_KI_STATE_LINE = 49, +}; + +// +// Input Models ... +struct X121XCatbInputs +{ + // + // Props ... + + // + // Market ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Short Period + ENUM_TIMEFRAMES scPeriod; // Short Period + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Medium Period + ENUM_TIMEFRAMES mcPeriod; // Medium Period + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Long Period + ENUM_TIMEFRAMES lcPeriod; // Long Period + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Hind Period + ENUM_TIMEFRAMES hcPeriod; // Hind Period + ENUM_X_MARKET_CYCLES appliedCycle; // Applied Cycle + + // + // Presentation ... + bool showBars; // Show Bars + bool showKI; // Show KI + bool showPV; // Show PV + bool showPVGolden; // Show PV Golden + bool showSar; // Show Sar + bool showTrend; // Show Trend + bool showATRBand; // Show ATR Band + bool showSignalBars; // Show Signal Bars + bool showHKSignalBars; // Show Hiken Ashi Signal Bars + + // + double rsiOBLevel; // RSI OB Level + double rsiOSLevel; // RSI OS Level + double adxThreshold; // ADX Threshold + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + // Constructor(s) ... + X121XCatbInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Presentation ... + showBars = false; // Show Bars + showKI = false; // Show KI + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Presentation ... + showBars = true; // Show Bars + showKI = false; // Show KI + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 1500; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showKI = false; + showPV = false; + showSar = false; + showTrend = false; + showATRBand = false; + showPVGolden = false; + showSignalBars = false; + showHKSignalBars = false; + + // + // drawSignals = false; + // drawTriggerBlock = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(appliedCycle) && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + return result; + } + + // +}; + +// +// Conditions ... +struct X121XCatbConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double kiBuffer[]; + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double kiStateBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + double rsiOBLevel; // Over Bought Level + double rsiOSLevel; // Over Sold Level + double adxThreshold; // Big Movement Threshold + + // + // Conditions ... + + // + // ATR Band ... + + // + bool isATRUp; + bool isATRDown; + + // + bool isClosedOverATRUpper; + bool isClosedUnderATRLower; + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + // KI ... + + // + bool isKIUp; + bool isKIDown; + + // + bool isKIBullish; + bool isKIBearish; + + // + bool isKISameAsLast; + + // + bool isKISwitchedToBullish; + bool isKISwitchedToBearish; + + // + // ADX ... + + // + bool isADXBiggerLast; + bool isADXLesserLast; + + // + bool isADXOverThreshold; + bool isADXUnderThreshold; + + // + bool isDXPBiggerThanDXN; + bool isDXNBiggerThanDXP; + + // + bool isADXBullish; + bool isADXBearish; + + // + bool isADXSwitchedToBullish; + bool isADXSwitchedToBearish; + + // + // RSI ... + + // + bool isRSIBullish; + bool isRSIBearish; + + // + bool isRSISwitchedToBullish; + bool isRSISwitchedToBearish; + + // + bool isRSIOB; + bool isRSIOS; + + // + bool isRSICrossedOverOB; + bool isRSICrossedOverOS; + + // + bool isRSICrossedUnderOB; + bool isRSICrossedUnderOS; + + // + // DELTA ... + + // + bool isDeltaUp; + bool isDeltaDown; + + // + bool isDeltaBullish; + bool isDeltaBearish; + + // + bool isDeltaSwitchedToBullish; + bool isDeltaSwitchedToBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish; + bool isVolumeBearish; + + // + bool isVolumeSwitchedToBullish; + bool isVolumeSwitchedToBearish; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish; + bool isSBarBearish; + + // + bool isSBarSwitchedToBullish; + bool isSBarSwitchedToBearish; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish; + bool isHKSBarBearish; + + // + bool isHKSBarSwitchedToBullish; + bool isHKSBarSwitchedToBearish; + + // + // TREND ... + + // + bool isTrendUp; + bool isTrendDown; + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + // PEAK ... + + // + bool isPeakSameLast; + bool isPeakOverLast; + bool isPeakUnderLast; + + // + // VALE ... + + // + bool isValeSameLast; + bool isValeOverLast; + bool isValeUnderLast; + + // + // Constructor ... + X121XCatbConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + SpecifiedClean(bars); + SpecifiedClean(kiBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(atrBuffer); + SpecifiedClean(rsiBuffer); + SpecifiedClean(adxBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + SpecifiedClean(adxpBuffer); + SpecifiedClean(adxnBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(deltaBuffer); + SpecifiedClean(trendBuffer); + SpecifiedClean(hkLowBuffer); + SpecifiedClean(hkOpenBuffer); + SpecifiedClean(hkHighBuffer); + SpecifiedClean(hkCloseBuffer); + SpecifiedClean(kiStateBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(atrUpperBuffer); + SpecifiedClean(atrLowerBuffer); + SpecifiedClean(sBarOpenBuffer); + SpecifiedClean(sBarCloseBuffer); + SpecifiedClean(trendStateBuffer); + SpecifiedClean(hkSBarOpenBuffer); + SpecifiedClean(peakGoldenBuffer); + SpecifiedClean(valeGoldenBuffer); + SpecifiedClean(hkSBarCloseBuffer); + SpecifiedClean(deltaSignalBuffer); + SpecifiedClean(bullishVolumeBuffer); + SpecifiedClean(bearishVolumeBuffer); + SpecifiedClean(bullishVolumeSignalBuffer); + SpecifiedClean(bearishVolumeSignalBuffer); + + // + ArraySetAsSeries(bars, true); + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + rsiOBLevel = 0; // Over Bought Level + rsiOSLevel = 0; // Over Sold Level + adxThreshold = 0; // Big Movement Threshold + + // + // Conditions ... + + // + // Conditions ... + + // + // ATR Band ... + + // + isATRUp = false; + isATRDown = false; + + // + isClosedOverATRUpper = false; + isClosedUnderATRLower = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // KI ... + + // + isKIUp = false; + isKIDown = false; + + // + isKIBullish = false; + isKIBearish = false; + + // + isKISameAsLast = false; + + // + isKISwitchedToBullish = false; + isKISwitchedToBearish = false; + + // + // ADX ... + + // + isADXBiggerLast = false; + isADXLesserLast = false; + + // + isADXOverThreshold = false; + isADXUnderThreshold = false; + + // + isDXPBiggerThanDXN = false; + isDXNBiggerThanDXP = false; + + // + isADXBullish = false; + isADXBearish = false; + + // + isADXSwitchedToBullish = false; + isADXSwitchedToBearish = false; + + // + // RSI ... + + // + isRSIBullish = false; + isRSIBearish = false; + + // + isRSISwitchedToBullish = false; + isRSISwitchedToBearish = false; + + // + isRSIOB = false; + isRSIOS = false; + + // + isRSICrossedOverOB = false; + isRSICrossedOverOS = false; + + // + isRSICrossedUnderOB = false; + isRSICrossedUnderOS = false; + + // + // DELTA ... + + // + isDeltaUp = false; + isDeltaDown = false; + + // + isDeltaBullish = false; + isDeltaBearish = false; + + // + isDeltaSwitchedToBullish = false; + isDeltaSwitchedToBearish = false; + + // + // VOLUME ... + + // + isVolumeBullish = false; + isVolumeBearish = false; + + // + isVolumeSwitchedToBullish = false; + isVolumeSwitchedToBearish = false; + // + // SIGNAL Bar ... + + // + isSBarBullish = false; + isSBarBearish = false; + + // + isSBarSwitchedToBullish = false; + isSBarSwitchedToBearish = false; + + // + // XHK Signal Bar ... + + // + isHKSBarBullish = false; + isHKSBarBearish = false; + + // + isHKSBarSwitchedToBullish = false; + isHKSBarSwitchedToBearish = false; + + // + // TREND ... + + // + isTrendUp = false; + isTrendDown = false; + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + // PEAK ... + + // + isPeakSameLast = false; + isPeakOverLast = false; + isPeakUnderLast = false; + + // + // VALE ... + + // + isValeSameLast = false; + isValeOverLast = false; + isValeUnderLast = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // ATR Band ... + + // + if (isATRUp) + { + bullishScore += score; + } + if (isClosedOverATRUpper) + { + bullishScore += score; + } + + // + if (isATRDown) + { + bearishScore += score; + } + if (isClosedUnderATRLower) + { + bearishScore += score; + } + + // + // SAR ... + + // + if (isSarBullish) + { + bullishScore += score; + } + if (isSarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSarBearish) + { + bearishScore += score; + } + if (isSarSwitchedToBearish) + { + bearishScore += score; + } + + // + // KI ... + + // + if (isKIUp) + { + bullishScore += score; + } + if (isKIBullish) + { + bullishScore += score; + } + if (isKISwitchedToBullish) + { + bullishScore += score; + } + + // + if (isKIDown) + { + bearishScore += score; + } + if (isKIBearish) + { + bearishScore += score; + } + if (isKISwitchedToBearish) + { + bearishScore += score; + } + + // + // ADX ... + + // + if (isADXBullish) + { + bullishScore += score; + } + if (isADXBiggerLast) + { + bullishScore += score; + } + if (isDXPBiggerThanDXN) + { + bullishScore += score; + } + if (isADXOverThreshold) + { + bullishScore += score; + } + if (isADXSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isADXBearish) + { + bearishScore += score; + } + if (isADXLesserLast) + { + bearishScore += score; + } + if (isDXNBiggerThanDXP) + { + bearishScore += score; + } + if (isADXUnderThreshold) + { + bearishScore += score; + } + if (isADXSwitchedToBearish) + { + bearishScore += score; + } + + // + // RSI ... + + // + if (isRSIOS) + { + bullishScore += score; + } + if (isRSIBullish) + { + bullishScore += score; + } + if (isRSICrossedOverOS) + { + bullishScore += score; + } + if (isRSICrossedOverOB) + { + bullishScore += score; + } + if (isRSISwitchedToBullish) + { + bullishScore += score; + } + + // + if (isRSIOB) + { + bearishScore += score; + } + if (isRSIBearish) + { + bearishScore += score; + } + if (isRSICrossedUnderOB) + { + bearishScore += score; + } + if (isRSICrossedUnderOS) + { + bearishScore += score; + } + if (isRSISwitchedToBearish) + { + bearishScore += score; + } + + // + // DELTA ... + + // + if (isDeltaUp) + { + bullishScore += score; + } + if (isDeltaBullish) + { + bullishScore += score; + } + if (isDeltaSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isDeltaDown) + { + bearishScore += score; + } + if (isDeltaBearish) + { + bearishScore += score; + } + if (isDeltaSwitchedToBearish) + { + bearishScore += score; + } + + // + // VOLUME ... + + // + if (isVolumeBullish) + { + bullishScore += score; + } + if (isVolumeSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isVolumeBearish) + { + bearishScore += score; + } + if (isVolumeSwitchedToBearish) + { + bearishScore += score; + } + + // + // SIGNAL Bar ... + + // + if (isSBarBullish) + { + bullishScore += score; + } + if (isSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSBarBearish) + { + bearishScore += score; + } + if (isSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // XHK Signal Bar ... + + // + if (isHKSBarBullish) + { + bullishScore += score; + } + if (isHKSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isHKSBarBearish) + { + bearishScore += score; + } + if (isHKSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // TREND ... + + // + if (isTrendUp) + { + bullishScore += score; + } + if (isTrendBullish) + { + bullishScore += score; + } + if (isTrendSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isTrendDown) + { + bearishScore += score; + } + if (isTrendBearish) + { + bearishScore += score; + } + if (isTrendSwitchedToBearish) + { + bearishScore += score; + } + + // + // PEAK and VALE ... + + // + if (isValeSameLast) + { + bullishScore += score; + } + if (isValeOverLast) + { + bullishScore += score; + } + if (isPeakOverLast) + { + bullishScore += score; + } + + // + if (isPeakSameLast) + { + bearishScore += score; + } + if (isPeakUnderLast) + { + bearishScore += score; + } + if (isValeUnderLast) + { + bearishScore += score; + } + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToXString(bullishScore) + separator + + "Bearish: " + ToXString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XCATB: " + separator + + "-----------------------" + separator + + "" + separator + + // + "-----------------------" + separator + + "ATR Band: " + separator + + "-----------------------" + separator + + ToXString("isATRUp", isATRUp, ignoreFalseConditions, separator) + + ToXString("isATRDown", isATRDown, ignoreFalseConditions, separator) + + ToXString("isClosedOverATRUpper", isClosedOverATRUpper, ignoreFalseConditions, separator) + + ToXString("isClosedUnderATRLower", isClosedUnderATRLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "KI: " + separator + + "-----------------------" + separator + + ToXString("isKIUp", isKIUp, ignoreFalseConditions, separator) + + ToXString("isKIDown", isKIDown, ignoreFalseConditions, separator) + + ToXString("isKIBullish", isKIBullish, ignoreFalseConditions, separator) + + ToXString("isKIBearish", isKIBearish, ignoreFalseConditions, separator) + + ToXString("isKISameAsLast", isKISameAsLast, ignoreFalseConditions, separator) + + ToXString("isKISwitchedToBullish", isKISwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isKISwitchedToBearish", isKISwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SAR: " + separator + + "-----------------------" + separator + + ToXString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToXString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToXString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "ADX: " + separator + + "-----------------------" + separator + + ToXString("isADXBiggerLast", isADXBiggerLast, ignoreFalseConditions, separator) + + ToXString("isADXLesserLast", isADXLesserLast, ignoreFalseConditions, separator) + + ToXString("isADXOverThreshold", isADXOverThreshold, ignoreFalseConditions, separator) + + ToXString("isADXUnderThreshold", isADXUnderThreshold, ignoreFalseConditions, separator) + + ToXString("isDXPBiggerThanDXN", isDXPBiggerThanDXN, ignoreFalseConditions, separator) + + ToXString("isDXNBiggerThanDXP", isDXNBiggerThanDXP, ignoreFalseConditions, separator) + + ToXString("isADXBullish", isADXBullish, ignoreFalseConditions, separator) + + ToXString("isADXBearish", isADXBearish, ignoreFalseConditions, separator) + + ToXString("isADXSwitchedToBullish", isADXSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isADXSwitchedToBearish", isADXSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "RSI: " + separator + + "-----------------------" + separator + + ToXString("isRSIBullish", isRSIBullish, ignoreFalseConditions, separator) + + ToXString("isRSIBearish", isRSIBearish, ignoreFalseConditions, separator) + + ToXString("isRSISwitchedToBullish", isRSISwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isRSISwitchedToBearish", isRSISwitchedToBearish, ignoreFalseConditions, separator) + + ToXString("isRSIOB", isRSIOB, ignoreFalseConditions, separator) + + ToXString("isRSIOS", isRSIOS, ignoreFalseConditions, separator) + + ToXString("isRSICrossedOverOB", isRSICrossedOverOB, ignoreFalseConditions, separator) + + ToXString("isRSICrossedOverOS", isRSICrossedOverOS, ignoreFalseConditions, separator) + + ToXString("isRSICrossedUnderOB", isRSICrossedUnderOB, ignoreFalseConditions, separator) + + ToXString("isRSICrossedUnderOS", isRSICrossedUnderOS, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "DELTA: " + separator + + "-----------------------" + separator + + ToXString("isDeltaUp", isDeltaUp, ignoreFalseConditions, separator) + + ToXString("isDeltaDown", isDeltaDown, ignoreFalseConditions, separator) + + ToXString("isDeltaBullish", isDeltaBullish, ignoreFalseConditions, separator) + + ToXString("isDeltaBearish", isDeltaBearish, ignoreFalseConditions, separator) + + ToXString("isDeltaSwitchedToBullish", isDeltaSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isDeltaSwitchedToBearish", isDeltaSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "VOLUME: " + separator + + "-----------------------" + separator + + ToXString("isVolumeBullish", isVolumeBullish, ignoreFalseConditions, separator) + + ToXString("isVolumeBearish", isVolumeBearish, ignoreFalseConditions, separator) + + ToXString("isVolumeSwitchedToBullish", isVolumeSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isVolumeSwitchedToBearish", isVolumeSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SIGNAL Bar: " + separator + + "-----------------------" + separator + + ToXString("isSBarBullish", isSBarBullish, ignoreFalseConditions, separator) + + ToXString("isSBarBearish", isSBarBearish, ignoreFalseConditions, separator) + + ToXString("isSBarSwitchedToBullish", isSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isSBarSwitchedToBearish", isSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "XHK Signal Bar: " + separator + + "-----------------------" + separator + + ToXString("isHKSBarBullish", isHKSBarBullish, ignoreFalseConditions, separator) + + ToXString("isHKSBarBearish", isHKSBarBearish, ignoreFalseConditions, separator) + + ToXString("isHKSBarSwitchedToBullish", isHKSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isHKSBarSwitchedToBearish", isHKSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Trend: " + separator + + "-----------------------" + separator + + ToXString("isTrendUp", isTrendUp, ignoreFalseConditions, separator) + + ToXString("isTrendDown", isTrendDown, ignoreFalseConditions, separator) + + ToXString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToXString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToXString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToXString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Peak: " + separator + + "-----------------------" + separator + + ToXString("isPeakSameLast", isPeakSameLast, ignoreFalseConditions, separator) + + ToXString("isPeakOverLast", isPeakOverLast, ignoreFalseConditions, separator) + + ToXString("isPeakUnderLast", isPeakUnderLast, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Vale: " + separator + + "-----------------------" + separator + + ToXString("isValeSameLast", isValeSameLast, ignoreFalseConditions, separator) + + ToXString("isValeOverLast", isValeOverLast, ignoreFalseConditions, separator) + + ToXString("isValeUnderLast", isValeUnderLast, ignoreFalseConditions, separator) + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCatbHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Buffers ... + double kiBuffer[]; + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double kiStateBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + // Market Shift ... + + // + // SAR ... + XDirectionShift lastSarBullish; + XDirectionShift lastSarBearish; + + // + // TREND ... + XDirectionShift lastTrendBullish; + XDirectionShift lastTrendBearish; + + // + // DELTA ... + XDirectionShift lastDeltaBullish; + XDirectionShift lastDeltaBearish; + + // + // VOLUME ... + XDirectionShift lastVolumeBullish; + XDirectionShift lastVolumeBearish; + + // + // SIGNAL Bar ... + XDirectionShift lastSignalBarBullish; + XDirectionShift lastSignalBarBearish; + + // + // XHK SIGNAL Bar ... + XDirectionShift lastHKSignalBarBullish; + XDirectionShift lastHKSignalBarBearish; + + // + // Constructors ... + XCX121XCatbHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCatbHelper() + { + // + mInputs.Clean(); + + // + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCatbInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcatb", + "", // Market ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.appliedCycle, + "", // Presentation ... + mInputs.showBars, + mInputs.showKI, + mInputs.showPV, + mInputs.showPVGolden, + mInputs.showSar, + mInputs.showTrend, + mInputs.showATRBand, + mInputs.showSignalBars, + mInputs.showHKSignalBars, + mInputs.startCalculationForLastBars + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + void Check(int barIndex = 0) + { + // + bool has = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + X121XCatbConditions conditions; + has = GetConditions( + conditions, + barIndex, + 4 // + ); + if (!has) + { + // + conditions.Clean(); + return; + } + + // + // Checking Shifts ... + + // + // SAR ... + + // + isBullish = conditions.isSarSwitchedToBullish; + isBearish = conditions.isSarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSarBullish.IsValid() + ? true + : lastSarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBullish.Clean(); + + // + lastSarBullish.type = "SAR"; + lastSarBullish.symbol = conditions.symbol; + lastSarBullish.period = conditions.period; + lastSarBullish.at = conditions.bars[1].time; + lastSarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSarBullish.after = conditions.sarBuffer[1]; + lastSarBullish.before = conditions.sarBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSarBearish.IsValid() + ? true + : lastSarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBearish.Clean(); + + // + lastSarBearish.type = "SAR"; + lastSarBearish.symbol = conditions.symbol; + lastSarBearish.period = conditions.period; + lastSarBearish.at = conditions.bars[1].time; + lastSarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSarBearish.after = conditions.sarBuffer[1]; + lastSarBearish.before = conditions.sarBuffer[2]; + } + } + + // + // TREND ... + + // + isBullish = conditions.isTrendSwitchedToBullish; + isBearish = conditions.isTrendSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastTrendBullish.IsValid() + ? true + : lastTrendBullish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBullish.Clean(); + + // + lastTrendBullish.type = "TREND"; + lastTrendBullish.symbol = conditions.symbol; + lastTrendBullish.period = conditions.period; + lastTrendBullish.at = conditions.bars[1].time; + lastTrendBullish.shiftTo = X_DIRECTION_BULLISH; + lastTrendBullish.after = conditions.trendBuffer[1]; + lastTrendBullish.before = conditions.trendBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastTrendBearish.IsValid() + ? true + : lastTrendBearish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBearish.Clean(); + + // + lastTrendBearish.type = "TREND"; + lastTrendBearish.symbol = conditions.symbol; + lastTrendBearish.period = conditions.period; + lastTrendBearish.at = conditions.bars[1].time; + lastTrendBearish.shiftTo = X_DIRECTION_BEARISH; + lastTrendBearish.after = conditions.trendBuffer[1]; + lastTrendBearish.before = conditions.trendBuffer[2]; + } + } + + // + // DELTA ... + + // + isBullish = + // + ( + // + // Delta is Up ... + conditions.deltaBuffer[1] > conditions.deltaBuffer[2] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[1] > conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Over Delta ... + conditions.deltaBuffer[1] > conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] <= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + isBearish = + // + ( + // + // Delta is Down ... + conditions.deltaBuffer[1] < conditions.deltaBuffer[2] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[1] < conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[1] < conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] >= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastDeltaBullish.IsValid() + ? true + : lastDeltaBullish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBullish.Clean(); + + // + lastDeltaBullish.type = "DELTA"; + lastDeltaBullish.symbol = conditions.symbol; + lastDeltaBullish.period = conditions.period; + lastDeltaBullish.at = conditions.bars[1].time; + lastDeltaBullish.shiftTo = X_DIRECTION_BULLISH; + lastDeltaBullish.after = conditions.bars[1].close; + lastDeltaBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastDeltaBearish.IsValid() + ? true + : lastDeltaBearish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBearish.Clean(); + + // + lastDeltaBearish.type = "DELTA"; + lastDeltaBearish.symbol = conditions.symbol; + lastDeltaBearish.period = conditions.period; + lastDeltaBearish.at = conditions.bars[1].time; + lastDeltaBearish.shiftTo = X_DIRECTION_BEARISH; + lastDeltaBearish.after = conditions.bars[1].close; + lastDeltaBearish.before = conditions.bars[2].close; + } + } + + // + // VOLUME ... + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] && + conditions.bullishVolumeSignalBuffer[2] <= conditions.bearishVolumeSignalBuffer[2] + // + ) + // + ; + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] && + conditions.bearishVolumeSignalBuffer[2] <= conditions.bullishVolumeSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastVolumeBullish.IsValid() + ? true + : lastVolumeBullish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBullish.Clean(); + + // + lastVolumeBullish.type = "VOLUME"; + lastVolumeBullish.symbol = conditions.symbol; + lastVolumeBullish.period = conditions.period; + lastVolumeBullish.at = conditions.bars[1].time; + lastVolumeBullish.shiftTo = X_DIRECTION_BULLISH; + lastVolumeBullish.after = conditions.bars[1].close; + lastVolumeBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastVolumeBearish.IsValid() + ? true + : lastVolumeBearish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBearish.Clean(); + + // + lastVolumeBearish.type = "VOLUME"; + lastVolumeBearish.symbol = conditions.symbol; + lastVolumeBearish.period = conditions.period; + lastVolumeBearish.at = conditions.bars[1].time; + lastVolumeBearish.shiftTo = X_DIRECTION_BEARISH; + lastVolumeBearish.after = conditions.bars[1].close; + lastVolumeBearish.before = conditions.bars[2].close; + } + } + + // + // SIGNAL Bar ... + + // + isBullish = conditions.isSBarSwitchedToBullish; + isBearish = conditions.isSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSignalBarBullish.IsValid() + ? true + : lastSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBullish.Clean(); + + // + lastSignalBarBullish.type = "SIGNALBAR"; + lastSignalBarBullish.symbol = conditions.symbol; + lastSignalBarBullish.period = conditions.period; + lastSignalBarBullish.at = conditions.bars[1].time; + lastSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSignalBarBullish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBullish.before = conditions.sBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSignalBarBearish.IsValid() + ? true + : lastSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBearish.Clean(); + + // + lastSignalBarBearish.type = "SIGNALBAR"; + lastSignalBarBearish.symbol = conditions.symbol; + lastSignalBarBearish.period = conditions.period; + lastSignalBarBearish.at = conditions.bars[1].time; + lastSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSignalBarBearish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBearish.before = conditions.sBarCloseBuffer[2]; + } + } + + // + // HKSIGNAL Bar ... + + // + isBullish = conditions.isHKSBarSwitchedToBullish; + isBearish = conditions.isHKSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastHKSignalBarBullish.IsValid() + ? true + : lastHKSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBullish.Clean(); + + // + lastHKSignalBarBullish.type = "HKSIGNALBAR"; + lastHKSignalBarBullish.symbol = conditions.symbol; + lastHKSignalBarBullish.period = conditions.period; + lastHKSignalBarBullish.at = conditions.bars[1].time; + lastHKSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastHKSignalBarBullish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBullish.before = conditions.hkSBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastHKSignalBarBearish.IsValid() + ? true + : lastHKSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBearish.Clean(); + + // + lastHKSignalBarBearish.type = "HKSIGNALBAR"; + lastHKSignalBarBearish.symbol = conditions.symbol; + lastHKSignalBarBearish.period = conditions.period; + lastHKSignalBarBearish.at = conditions.bars[1].time; + lastHKSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastHKSignalBarBearish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBearish.before = conditions.hkSBarCloseBuffer[2]; + } + } + + // + // Cleanup Resources ... + + // + conditions.Clean(); + } + + // + // Inputs ... + + // + X121XCatbInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCatbInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // Readers ... + + // + // SAR ... + + // + double GetKI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiBuffer[barIndex]; + } + + // + int CopyKI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiBuffer, + buffer, + forceClean + // + ); + } + + // + // KI State ... + + // + double GetKIState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiStateBuffer[barIndex]; + } + + // + int CopyKIState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarStateBuffer[barIndex]; + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarStateBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK Golden ... + + // + double GetPeakGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakGoldenBuffer[barIndex]; + } + + // + int CopyPeakGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE Golden ... + + // + double GetValeGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeGoldenBuffer[barIndex]; + } + + // + int CopyValeGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Upper ... + + // + double GetATRUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrUpperBuffer[barIndex]; + } + + // + int CopyATRUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Lower ... + + // + double GetATRLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrLowerBuffer[barIndex]; + } + + // + int CopyATRLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendBuffer[barIndex]; + } + + // + int CopyTrend( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND State ... + + // + double GetTrendState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendStateBuffer[barIndex]; + } + + // + int CopyTrendState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SIGNAL Bar ... + + // + // OPEN ... + + // + double GetSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarOpenBuffer[barIndex]; + } + + // + int CopySBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarCloseBuffer[barIndex]; + } + + // + int CopySBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK SIGNAL Bar ... + + // + // OPEN ... + + // + double GetHKSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarOpenBuffer[barIndex]; + } + + // + int CopyHKSBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetHKSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarCloseBuffer[barIndex]; + } + + // + int CopyHKSBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXP ... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxpBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxpBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXN ... + + // + double GetADXN( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxnBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxnBuffer[barIndex]; + } + + // + int CopyADXN( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxnBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA ... + + // + double GetDelta( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaBuffer[barIndex]; + } + + // + int CopyDelta( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA Signal ... + + // + double GetDeltaSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaSignalBuffer[barIndex]; + } + + // + int CopyDeltaSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME ... + + // + // Bullish ... + + // + double GetBullishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeBuffer[barIndex]; + } + + // + int CopyBullishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeBuffer[barIndex]; + } + + // + int CopyBearishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME Signal ... + + // + // Bullish ... + + // + double GetBullishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBullishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBearishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK ... + + // + // Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkOpenBuffer[barIndex]; + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkHighBuffer[barIndex]; + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkHighBuffer, + buffer, + forceClean + // + ); + } + + // + // Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkLowBuffer[barIndex]; + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkLowBuffer, + buffer, + forceClean + // + ); + } + + // + // Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkCloseBuffer[barIndex]; + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + int CopyRSI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // Tools ... + + // + void Update( + int barIndex // Bar Index + ) + { + // + Calculate(barIndex); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCatbConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + // Filling Bars ... + int barsCount = GetBars( + conditions.bars, + mSymbol, + mPeriod, + barIndex, + loopback // + ); + result = barsCount == loopback; + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // + // Buffers ... + + CopyKI( + zIndex, + loopback, + conditions.kiBuffer // + ); + + // + CopyKIState( + zIndex, + loopback, + conditions.kiStateBuffer // + ); + + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyPeakGolden( + zIndex, + loopback, + conditions.peakGoldenBuffer // + ); + + // + CopyValeGolden( + zIndex, + loopback, + conditions.valeGoldenBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyATRUpper( + zIndex, + loopback, + conditions.atrUpperBuffer // + ); + + // + CopyATRLower( + zIndex, + loopback, + conditions.atrLowerBuffer // + ); + + // + CopyTrend( + zIndex, + loopback, + conditions.trendBuffer // + ); + + // + CopyTrendState( + zIndex, + loopback, + conditions.trendStateBuffer // + ); + + // + CopySBarOpen( + zIndex, + loopback, + conditions.sBarOpenBuffer // + ); + + // + CopySBarClose( + zIndex, + loopback, + conditions.sBarCloseBuffer // + ); + + // + CopyHKSBarOpen( + zIndex, + loopback, + conditions.hkSBarOpenBuffer // + ); + + // + CopyHKSBarClose( + zIndex, + loopback, + conditions.hkSBarCloseBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxpBuffer // + ); + + // + CopyADXN( + zIndex, + loopback, + conditions.adxnBuffer // + ); + + // + CopyDelta( + zIndex, + loopback, + conditions.deltaBuffer // + ); + + // + CopyDeltaSignal( + zIndex, + loopback, + conditions.deltaSignalBuffer // + ); + + // + CopyBullishVolume( + zIndex, + loopback, + conditions.bullishVolumeBuffer // + ); + + // + CopyBearishVolume( + zIndex, + loopback, + conditions.bearishVolumeBuffer // + ); + + // + CopyBullishVolumeSignal( + zIndex, + loopback, + conditions.bullishVolumeSignalBuffer // + ); + + // + CopyBearishVolumeSignal( + zIndex, + loopback, + conditions.bearishVolumeSignalBuffer // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + // Calculate ... + + // + double _rsiOBLevel = mInputs.rsiOBLevel; // Over Bought Level + double _rsiOSLevel = mInputs.rsiOSLevel; // Over Sold Level + double _adxThreshold = mInputs.adxThreshold; // Big Movement Threshold + + // + // Reading Values ... + + // + // ATR Upper ... + double zATRUpper = conditions.atrUpperBuffer[zIDX]; + double cATRUpper = conditions.atrUpperBuffer[cIDX]; + double pATRUpper = conditions.atrUpperBuffer[pIDX]; + double p2ATRUpper = conditions.atrUpperBuffer[p2IDX]; + double p3ATRUpper = conditions.atrUpperBuffer[p3IDX]; + + // + // ATR Lower ... + double zATRLower = conditions.atrLowerBuffer[zIDX]; + double cATRLower = conditions.atrLowerBuffer[cIDX]; + double pATRLower = conditions.atrLowerBuffer[pIDX]; + double p2ATRLower = conditions.atrLowerBuffer[p2IDX]; + double p3ATRLower = conditions.atrLowerBuffer[p3IDX]; + + // + // KI ... + + // + double zKI = conditions.kiBuffer[zIDX]; + double cKI = conditions.kiBuffer[cIDX]; + double pKI = conditions.kiBuffer[pIDX]; + double p2KI = conditions.kiBuffer[p2IDX]; + double p3KI = conditions.kiBuffer[p3IDX]; + + // + double zKIState = conditions.kiStateBuffer[zIDX]; + double cKIState = conditions.kiStateBuffer[cIDX]; + double pKIState = conditions.kiStateBuffer[pIDX]; + double p2KIState = conditions.kiStateBuffer[p2IDX]; + double p3KIState = conditions.kiStateBuffer[p3IDX]; + + // + // SAR ... + + // + double zSAR = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSAR = conditions.sarBuffer[pIDX]; + double p2SAR = conditions.sarBuffer[p2IDX]; + double p3SAR = conditions.sarBuffer[p3IDX]; + + // + double zSarState = conditions.sarStateBuffer[zIDX]; + double cSarState = conditions.sarStateBuffer[cIDX]; + double pSarState = conditions.sarStateBuffer[pIDX]; + double p2SarState = conditions.sarStateBuffer[p2IDX]; + double p3SarState = conditions.sarStateBuffer[p3IDX]; + + // + // ADX ... + + // + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + double p3ADX = conditions.adxBuffer[p3IDX]; + + // + // ADX P ... + + // + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + double p3ADXP = conditions.adxpBuffer[p3IDX]; + + // + // ADX N ... + + // + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + double p3ADXN = conditions.adxnBuffer[p3IDX]; + + // + // RSI ... + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + double p3RSI = conditions.rsiBuffer[p3IDX]; + + // + // SIGNAL Bar ... + + // + double zSBarO = conditions.sBarOpenBuffer[zIDX]; + double cSBarO = conditions.sBarOpenBuffer[cIDX]; + double pSBarO = conditions.sBarOpenBuffer[pIDX]; + double p2SBarO = conditions.sBarOpenBuffer[p2IDX]; + double p3SBarO = conditions.sBarOpenBuffer[p3IDX]; + + // + double zSBarC = conditions.sBarCloseBuffer[zIDX]; + double cSBarC = conditions.sBarCloseBuffer[cIDX]; + double pSBarC = conditions.sBarCloseBuffer[pIDX]; + double p2SBarC = conditions.sBarCloseBuffer[p2IDX]; + double p3SBarC = conditions.sBarCloseBuffer[p3IDX]; + + // + // XHK SIGNAL Bar ... + + // + double zHKSBarO = conditions.hkSBarOpenBuffer[zIDX]; + double cHKSBarO = conditions.hkSBarOpenBuffer[cIDX]; + double pHKSBarO = conditions.hkSBarOpenBuffer[pIDX]; + double p2HKSBarO = conditions.hkSBarOpenBuffer[p2IDX]; + double p3HKSBarO = conditions.hkSBarOpenBuffer[p3IDX]; + + // + double zHKSBarC = conditions.hkSBarCloseBuffer[zIDX]; + double cHKSBarC = conditions.hkSBarCloseBuffer[cIDX]; + double pHKSBarC = conditions.hkSBarCloseBuffer[pIDX]; + double p2HKSBarC = conditions.hkSBarCloseBuffer[p2IDX]; + double p3HKSBarC = conditions.hkSBarCloseBuffer[p3IDX]; + + // + // TREND ... + + // + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + double p3Trend = conditions.trendBuffer[p3IDX]; + + // + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + double p3TrendState = conditions.trendStateBuffer[p3IDX]; + + // + // XPV ... + + // + double zPEAK = conditions.peakBuffer[zIDX]; + double cPEAK = conditions.peakBuffer[cIDX]; + double pPEAK = conditions.peakBuffer[pIDX]; + double p2PEAK = conditions.peakBuffer[p2IDX]; + double p3PEAK = conditions.peakBuffer[p3IDX]; + + // + double zVALE = conditions.valeBuffer[zIDX]; + double cVALE = conditions.valeBuffer[cIDX]; + double pVALE = conditions.valeBuffer[pIDX]; + double p2VALE = conditions.valeBuffer[p2IDX]; + double p3VALE = conditions.valeBuffer[p3IDX]; + + // + // DELTA ... + + // + double zDelta = conditions.deltaBuffer[zIDX]; + double cDelta = conditions.deltaBuffer[cIDX]; + double pDelta = conditions.deltaBuffer[pIDX]; + double p2Delta = conditions.deltaBuffer[p2IDX]; + double p3Delta = conditions.deltaBuffer[p3IDX]; + + // + double zDeltaSignal = conditions.deltaSignalBuffer[zIDX]; + double cDeltaSignal = conditions.deltaSignalBuffer[cIDX]; + double pDeltaSignal = conditions.deltaSignalBuffer[pIDX]; + double p2DeltaSignal = conditions.deltaSignalBuffer[p2IDX]; + double p3DeltaSignal = conditions.deltaSignalBuffer[p3IDX]; + + // + // VOLUME ... + + // + double zBullishVolume = conditions.bullishVolumeBuffer[zIDX]; + double cBullishVolume = conditions.bullishVolumeBuffer[cIDX]; + double pBullishVolume = conditions.bullishVolumeBuffer[pIDX]; + double p2BullishVolume = conditions.bullishVolumeBuffer[p2IDX]; + double p3BullishVolume = conditions.bullishVolumeBuffer[p3IDX]; + + // + double zBearishVolume = conditions.bearishVolumeBuffer[zIDX]; + double cBearishVolume = conditions.bearishVolumeBuffer[cIDX]; + double pBearishVolume = conditions.bearishVolumeBuffer[pIDX]; + double p2BearishVolume = conditions.bearishVolumeBuffer[p2IDX]; + double p3BearishVolume = conditions.bearishVolumeBuffer[p3IDX]; + + // + double zBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[zIDX]; + double cBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[cIDX]; + double pBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[pIDX]; + double p2BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p2IDX]; + double p3BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p3IDX]; + + // + double zBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[zIDX]; + double cBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[cIDX]; + double pBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[pIDX]; + double p2BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p2IDX]; + double p3BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p3IDX]; + + // + // ATR Band ... + + // + bool isATRUp = + cATRUpper > pATRUpper && + cATRLower > pATRLower; + bool isATRDown = + cATRUpper < pATRUpper && + cATRLower < pATRLower; + + // + bool isClosedOverATRUpper = + conditions.bars[cIDX].close > cATRUpper; + bool isClosedUnderATRLower = + conditions.bars[cIDX].close < cATRLower; + + // + // KI ... + + // + bool isKIUp = cKI > pKI; + bool isKIDown = cKI < pKI; + + // + bool isKIBullish = cKIState > 0; + bool isKIBearish = cKIState < 0; + + // + bool isKISameAsLast = cKI == pKI; + + // + bool isKISwitchedToBullish = + cKIState > 0 && + pKIState <= 0; + + // + bool isKISwitchedToBearish = + cKIState < 0 && + pKIState >= 0; + + // + // SAR ... + + // + bool isSarBullish = cSarState > 0; + bool isSarBearish = cSarState < 0; + + // + bool isSarSwitchedToBullish = + cSarState > 0 && + pSarState <= 0; + bool isSarSwitchedToBearish = + cSarState < 0 && + pSarState >= 0; + + // + // ADX ... + + // + bool isADXBiggerLast = + cADX > pADX; + bool isADXLesserLast = + cADX < pADX; + + // + bool isPADXBiggerLast = + pADX > p2ADX; + bool isPADXLesserLast = + pADX < p2ADX; + + // + bool isADXOverThreshold = + cADX > _adxThreshold; + bool isADXUnderThreshold = + cADX < _adxThreshold; + + // + bool isPADXOverThreshold = + pADX > _adxThreshold; + bool isPADXUnderThreshold = + pADX < _adxThreshold; + + // + bool isDXPBiggerThanDXN = + cADXP > cADXN; + bool isDXNBiggerThanDXP = + cADXN > cADXP; + + // + bool isPDXPBiggerThanDXN = + pADXP > pADXN; + bool isPDXNBiggerThanDXP = + pADXN > pADXP; + + // + bool isADXBullish = + isADXBiggerLast && + isADXOverThreshold; + bool isADXBearish = + isADXLesserLast && + isADXUnderThreshold; + + // + bool isPADXBullish = + isPADXBiggerLast && + isPADXOverThreshold; + bool isPADXBearish = + isPADXLesserLast && + isPADXUnderThreshold; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + // RSI ... + + // + bool isRSIBullish = + cRSI > pRSI; + bool isRSIBearish = + cRSI < pRSI; + + // + bool isRSISwitchedToBullish = + cRSI > pRSI && + pRSI <= cRSI; + bool isRSISwitchedToBearish = + cRSI < pRSI && + pRSI >= cRSI; + + // + bool isRSIOB = + cRSI > _rsiOBLevel; + bool isRSIOS = + cRSI < _rsiOSLevel; + + // + bool isRSICrossedOverOB = + cRSI > _rsiOBLevel && + pRSI <= _rsiOBLevel; + bool isRSICrossedOverOS = + cRSI > _rsiOSLevel && + pRSI <= _rsiOSLevel; + + // + bool isRSICrossedUnderOB = + cRSI < _rsiOBLevel && + pRSI >= _rsiOBLevel; + bool isRSICrossedUnderOS = + cRSI < _rsiOSLevel && + pRSI >= _rsiOSLevel; + + // + // DELTA ... + + // + bool isDeltaUp = + cDelta > pDelta; + bool isDeltaDown = + cDelta < pDelta; + + // + bool isDeltaBullish = + cDelta > pDelta && + cDeltaSignal > cDelta && + cDeltaSignal > pDeltaSignal; + bool isPDeltaBullish = + pDelta > p2Delta && + pDeltaSignal > pDelta && + pDeltaSignal > p2DeltaSignal; + + // + bool isDeltaBearish = + cDelta < pDelta && + cDeltaSignal < cDelta && + cDeltaSignal < pDeltaSignal; + bool isPDeltaBearish = + pDelta < p2Delta && + pDeltaSignal < pDelta && + pDeltaSignal < p2DeltaSignal; + + // + bool isDeltaSwitchedToBullish = + isDeltaBullish && + !isPDeltaBullish; + bool isDeltaSwitchedToBearish = + isDeltaBearish && + !isPDeltaBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish = + cBullishVolume > pBullishVolume && + cBullishVolume > cBearishVolume; + bool isVolumeBearish = + cBearishVolume > pBearishVolume && + cBearishVolume > cBullishVolume; + + // + bool isVolumeSwitchedToBullish = + isVolumeBullish && + cBullishVolumeSignal > cBearishVolumeSignal && + pBullishVolumeSignal <= pBearishVolumeSignal; + bool isVolumeSwitchedToBearish = + isVolumeBearish && + cBearishVolumeSignal > cBullishVolumeSignal && + pBearishVolumeSignal <= pBullishVolumeSignal; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish = + cSBarO < cSBarC; + bool isSBarBearish = + cSBarO > cSBarC; + + // + bool isSBarSwitchedToBullish = + cSBarO < cSBarC && + pSBarO >= pSBarC; + bool isSBarSwitchedToBearish = + cSBarO > cSBarC && + pSBarO <= pSBarC; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish = + cHKSBarO < cHKSBarC; + bool isHKSBarBearish = + cHKSBarO > cHKSBarC; + + // + bool isHKSBarSwitchedToBullish = + cHKSBarO < cHKSBarC && + pHKSBarO >= pHKSBarC; + bool isHKSBarSwitchedToBearish = + cHKSBarO > cHKSBarC && + pHKSBarO <= pHKSBarC; + + // + // TREND ... + + // + bool isTrendUp = + cTrend > pTrend; + bool isTrendDown = + cTrend < pTrend; + + // + bool isTrendBullish = + cTrendState > 0; + bool isTrendBearish = + cTrendState < 0; + + // + bool isTrendSwitchedToBullish = + isTrendUp && + cTrendState > 0 && + pTrendState <= 0; + bool isTrendSwitchedToBearish = + isTrendDown && + cTrendState < 0 && + pTrendState >= 0; + + // + // PEAK ... + + // + bool isPeakSameLast = + cPEAK > 0 && + cPEAK == pPEAK; + bool isPeakOverLast = + pPEAK > 0 && + cPEAK > pPEAK; + bool isPeakUnderLast = + cPEAK > 0 && + cPEAK < pPEAK; + + // + // VALE ... + + // + bool isValeSameLast = + cVALE > 0 && + cVALE == pVALE; + bool isValeOverLast = + pVALE > 0 && + cVALE > pVALE; + bool isValeUnderLast = + cVALE > 0 && + cVALE < pVALE; + + // + // Attached ... + + // + conditions.isKIUp = isKIUp; + conditions.isATRUp = isATRUp; + conditions.isRSIOB = isRSIOB; + conditions.isRSIOS = isRSIOS; + conditions.isKIDown = isKIDown; + conditions.isDeltaUp = isDeltaUp; + conditions.isATRDown = isATRDown; + conditions.isTrendUp = isTrendUp; + conditions.rsiOBLevel = _rsiOBLevel; + conditions.rsiOSLevel = _rsiOSLevel; + conditions.isDeltaDown = isDeltaDown; + conditions.isTrendDown = isTrendDown; + conditions.isKIBullish = isKIBullish; + conditions.isKIBearish = isKIBearish; + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isADXBullish = isADXBullish; + conditions.isADXBearish = isADXBearish; + conditions.isRSIBullish = isRSIBullish; + conditions.isRSIBearish = isRSIBearish; + conditions.adxThreshold = _adxThreshold; + conditions.isSBarBullish = isSBarBullish; + conditions.isSBarBearish = isSBarBearish; + conditions.isKISameAsLast = isKISameAsLast; + conditions.isDeltaBullish = isDeltaBullish; + conditions.isDeltaBearish = isDeltaBearish; + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isPeakSameLast = isPeakSameLast; + conditions.isPeakOverLast = isPeakOverLast; + conditions.isValeSameLast = isValeSameLast; + conditions.isValeOverLast = isValeOverLast; + conditions.isVolumeBullish = isVolumeBullish; + conditions.isVolumeBearish = isVolumeBearish; + conditions.isADXBiggerLast = isADXBiggerLast; + conditions.isADXLesserLast = isADXLesserLast; + conditions.isHKSBarBullish = isHKSBarBullish; + conditions.isHKSBarBearish = isHKSBarBearish; + conditions.isPeakUnderLast = isPeakUnderLast; + conditions.isValeUnderLast = isValeUnderLast; + conditions.isRSICrossedOverOB = isRSICrossedOverOB; + conditions.isRSICrossedOverOS = isRSICrossedOverOS; + conditions.isADXOverThreshold = isADXOverThreshold; + conditions.isDXPBiggerThanDXN = isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = isDXNBiggerThanDXP; + conditions.isRSICrossedUnderOB = isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = isRSICrossedUnderOS; + conditions.isADXUnderThreshold = isADXUnderThreshold; + conditions.isClosedOverATRUpper = isClosedOverATRUpper; + conditions.isKISwitchedToBullish = isKISwitchedToBullish; + conditions.isKISwitchedToBearish = isKISwitchedToBearish; + conditions.isClosedUnderATRLower = isClosedUnderATRLower; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isADXSwitchedToBullish = isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = isADXSwitchedToBearish; + conditions.isRSISwitchedToBullish = isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = isRSISwitchedToBearish; + conditions.isSBarSwitchedToBullish = isSBarSwitchedToBullish; + conditions.isSBarSwitchedToBearish = isSBarSwitchedToBearish; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + conditions.isDeltaSwitchedToBullish = isDeltaSwitchedToBullish; + conditions.isDeltaSwitchedToBearish = isDeltaSwitchedToBearish; + conditions.isVolumeSwitchedToBullish = isVolumeSwitchedToBullish; + conditions.isVolumeSwitchedToBearish = isVolumeSwitchedToBearish; + conditions.isHKSBarSwitchedToBullish = isHKSBarSwitchedToBullish; + conditions.isHKSBarSwitchedToBearish = isHKSBarSwitchedToBearish; + + // + // Cleanup Resources ... + + // + Cleanup(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCatbInputs mInputs; // Inputs ... + + // + // Buffers ... + // Define in Public ... + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + X121_XCATB_KI_LINE, + barIndex, + maxRequiredBars, + kiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_KI_STATE_LINE, + barIndex, + maxRequiredBars, + kiStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_STATE_LINE, + barIndex, + maxRequiredBars, + sarStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_GOLDEN_LINE, + barIndex, + maxRequiredBars, + peakGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_GOLDEN_LINE, + barIndex, + maxRequiredBars, + valeGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_UPPER_LINE, + barIndex, + maxRequiredBars, + atrUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_LOWER_LINE, + barIndex, + maxRequiredBars, + atrLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_LINE, + barIndex, + maxRequiredBars, + trendBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_STATE_LINE, + barIndex, + maxRequiredBars, + trendStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_O_LINE, + barIndex, + maxRequiredBars, + sBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_C_LINE, + barIndex, + maxRequiredBars, + sBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_O_LINE, + barIndex, + maxRequiredBars, + hkSBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_C_LINE, + barIndex, + maxRequiredBars, + hkSBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_RSI_LINE, + barIndex, + maxRequiredBars, + rsiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADX_LINE, + barIndex, + maxRequiredBars, + adxBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXP_LINE, + barIndex, + maxRequiredBars, + adxpBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXN_LINE, + barIndex, + maxRequiredBars, + adxnBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_LINE, + barIndex, + maxRequiredBars, + deltaBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_SIGNAL_LINE, + barIndex, + maxRequiredBars, + deltaSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BULLISH_LINE, + barIndex, + maxRequiredBars, + bullishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BEARISH_LINE, + barIndex, + maxRequiredBars, + bearishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bullishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bearishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_LINE, + barIndex, + maxRequiredBars, + atrBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_O_LINE, + barIndex, + maxRequiredBars, + hkOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_H_LINE, + barIndex, + maxRequiredBars, + hkHighBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_L_LINE, + barIndex, + maxRequiredBars, + hkLowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_C_LINE, + barIndex, + maxRequiredBars, + hkCloseBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + kiBuffer, + maxAllowed // + ); + + // + CleanupArray( + kiStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxpBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxnBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkCloseBuffer, + maxAllowed // + ); + } + + // +}; + +// +// Extensions ... + +// +enum ENUM_XCATB_DIRECTION_SHIFT_TYPES +{ + XCATB_DIRECTION_SHIFT_TYPE_NONE, // None + XCATB_DIRECTION_SHIFT_TYPE_SAR, // XSARB + XCATB_DIRECTION_SHIFT_TYPE_TREND, // XTRNDB + XCATB_DIRECTION_SHIFT_TYPE_DELTA, // XDELTAB + XCATB_DIRECTION_SHIFT_TYPE_VOLUME, // XVLMB + XCATB_DIRECTION_SHIFT_TYPE_SIGNAL_BAR, // XSBARB + XCATB_DIRECTION_SHIFT_TYPE_HK_SIGNAL_BAR, // XHKSBARB +}; + +// +bool IsValid(ENUM_XCATB_DIRECTION_SHIFT_TYPES value) +{ + return value != XCATB_DIRECTION_SHIFT_TYPE_NONE; +} + +// +string ToXString(ENUM_XCATB_DIRECTION_SHIFT_TYPES value) +{ + return EnumToString(value); +} + +// +ENUM_XCATB_DIRECTION_SHIFT_TYPES GetDirectionShiftType(XBoxZone &box) +{ + // + ENUM_XCATB_DIRECTION_SHIFT_TYPES result = XCATB_DIRECTION_SHIFT_TYPE_NONE; + + // + if (!box.IsValid()) + { + return result; + } + + // + ENUM_XCATB_DIRECTION_SHIFT_TYPES all[] = { + XCATB_DIRECTION_SHIFT_TYPE_SAR, + XCATB_DIRECTION_SHIFT_TYPE_TREND, + XCATB_DIRECTION_SHIFT_TYPE_DELTA, + XCATB_DIRECTION_SHIFT_TYPE_VOLUME, + XCATB_DIRECTION_SHIFT_TYPE_SIGNAL_BAR, + XCATB_DIRECTION_SHIFT_TYPE_HK_SIGNAL_BAR, + }; + + // + int count = ArraySize(all); + for (int i = 0; i < count; i++) + { + // + if (box.type == ToXString(all[i])) + { + // + result = all[i]; + break; + } + } + + // + return result; +} + +// +bool IsDirectionShift(XBoxZone &box) +{ + // + bool result = false; + + // + result = IsValid(GetDirectionShiftType(box)); + + // + return result; +} + +/** + * Generate Sar Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateSarDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastSarBullish; + XDirectionShift lastBearish = helper.lastSarBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XSARB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Trend Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateTrendDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBullish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBearish.IsValid() && + // + // Current Close is Over previous ... + conditions.bars[cIDX].close > helper.lastTrendBearish.after && + // + // Before close is not Over previous ... + conditions.bars[pIDX].close <= helper.lastTrendBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBearish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastTrendBullish.after && + // + // Before close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastTrendBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastTrendBullish; + XDirectionShift lastBearish = helper.lastTrendBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XTRNDB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Delta Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateDeltaDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + // Check State ... + ( + // + // Delta is Up ... + conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Over Delta Signal ... + conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastDeltaBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastDeltaBearish.after + // + ; + + // + bool isBearish = + // + // Check State ... + ( + // + // Delta is Down ... + conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBullish.IsValid() && + // + // Current Close is Under last ... + conditions.bars[cIDX].close < helper.lastDeltaBullish.after && + // + // Before Close is not Under last ... + conditions.bars[pIDX].close >= helper.lastDeltaBullish.after + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastDeltaBullish; + XDirectionShift lastBearish = helper.lastDeltaBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XDELTAB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Volume Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateVolumeDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastVolumeBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastVolumeBearish.after + // + ; + + // + bool isBearish = + // + ( + // + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBullish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close < helper.lastVolumeBullish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close >= helper.lastVolumeBullish.after + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastVolumeBullish; + XDirectionShift lastBearish = helper.lastVolumeBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XVLMB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Signal Bar Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateSignalBarDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Check Direction ... + conditions.isSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Check Direction ... + conditions.isSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastSignalBarBullish; + XDirectionShift lastBearish = helper.lastSignalBarBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XSBARB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate HK Signal Bar Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateHKSignalBarDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Check Direction ... + conditions.isHKSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Check Direction ... + conditions.isHKSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastHKSignalBarBullish; + XDirectionShift lastBearish = helper.lastHKSignalBarBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XHKSBARB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14040626/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..6771036 --- /dev/null +++ b/BKPS/14040626/Helpers/x-saherelm.x121.xcc.helper.mq5 @@ -0,0 +1,259 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCCInputs +{ + // + // Props ... + + // + // Chart Style ... + ENUM_CHART_MODE mode; // Mode + color upColor; // Up Color + color downColor; // Down Color + color lineColor; // Line mode and Doji candlestick Color + color bearishColor; // Bullish Color + color bullishColor; // Bearish Color + color volumesColor; // Volumes Color + + // + // Presentation ... + bool showCandles; // Show Candles + + // + // Constructor(s) ... + X121XCCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + mode = CHART_CANDLES; + + // + upColor = CLR_NONE; + downColor = CLR_NONE; + lineColor = CLR_NONE; + bearishColor = CLR_NONE; + bullishColor = CLR_NONE; + volumesColor = CLR_NONE; + + // + showCandles = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + mode = CHART_CANDLES; + + // + upColor = clrLime; + downColor = clrRed; + lineColor = clrLime; + bearishColor = clrRed; + bullishColor = clrLime; + volumesColor = clrGreen; + // + showCandles = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + showCandles = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XCX121XCCHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCCHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCCHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + mInputs.mode, // Mode + mInputs.upColor, // Up Color + mInputs.downColor, // Down Color + mInputs.lineColor, // Line mode and Doji candlestick Color + mInputs.bullishColor, // Bearish Color + mInputs.bearishColor, // Bullish Color + mInputs.volumesColor, // Volumes Color + // + // Presentation ... + "", + mInputs.showCandles // Show Candles + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCCInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040626/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14040626/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..6c5284e --- /dev/null +++ b/BKPS/14040626/Helpers/x-saherelm.x121.xct.helper.mq5 @@ -0,0 +1,241 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCTHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCTInputs +{ + // + // Props ... + + // + string font; // Font + int fontSize; // Font Size; + color clr; // Text Color + ENUM_BASE_CORNER corner; // Text Position + + // + // Presentation ... + bool showCandleTime; // Show Candle Time + + // + // Constructor(s) ... + X121XCTInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + font = NULL; + fontSize = 15; + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + font = "Arial"; + fontSize = 15; + clr = clrYellow; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + showCandleTime = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XCX121XCTHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCTHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCTHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xct", + // + // Inputs ... + mInputs.fontSize, // Font Size ... + mInputs.font, // Font ... + mInputs.clr, // Text Color ... + mInputs.corner, // Text Position ... + // + // Presentation ... + "", + mInputs.showCandleTime // Show Candle Time + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040626/Helpers/x-saherelm.xom1.helper.mq5 b/BKPS/14040626/Helpers/x-saherelm.xom1.helper.mq5 new file mode 100644 index 0000000..b461865 --- /dev/null +++ b/BKPS/14040626/Helpers/x-saherelm.xom1.helper.mq5 @@ -0,0 +1,2056 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXOM1Helper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_XOM1_BUFFERS +{ + XOM1_MA_FAST_LINE = 0, + XOM1_MA_FAST_COLOR_LINE = 1, + XOM1_MA_FAST_STATE_LINE = 10, + XOM1_MA_SLOW_LINE = 2, + XOM1_MA_SLOW_COLOR_LINE = 3, + XOM1_MA_SLOW_STATE_LINE = 11, + XOM1_SAR_LINE = 4, + XOM1_SAR_COLOR_LINE = 5, + XOM1_SAR_STATE_LINE = 12, + XOM1_PEAK_LINE = 6, + XOM1_VALE_LINE = 7, + XOM1_FINO_UPPER_LINE = 8, + XOM1_FINO_LOWER_LINE = 9, + // 10 Ma Fast State + // 11 Ma Slow State + // 12 Sar State + XOM1_SC_HH_LINE = 13, + XOM1_SC_LL_LINE = 14, + XOM1_MC_HH_LINE = 15, + XOM1_MC_LL_LINE = 16, + XOM1_LC_HH_LINE = 17, + XOM1_LC_LL_LINE = 18, + XOM1_HC_HH_LINE = 19, + XOM1_HC_LL_LINE = 20, +}; + +// +// Input Models ... +struct XOM1Inputs +{ + // + // Props ... + + // + // Calculation ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Short Period + ENUM_TIMEFRAMES scPeriod; // Short Period + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Medium Period + ENUM_TIMEFRAMES mcPeriod; // Medium Period + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Long Period + ENUM_TIMEFRAMES lcPeriod; // Long Period + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Hind Period + ENUM_TIMEFRAMES hcPeriod; // Hind Period + ENUM_SERIESMODE upperMode; // Peak Method + ENUM_SERIESMODE lowerMode; // Vale Method + ENUM_X_FIBO_LEVELS upperZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS lowerZoneLevel; // Lower Zone Level + double sarStep; // SAR Step + double sarMax; // SAR Maximum + ENUM_MA_METHOD maMethod; // MA Method + ENUM_APPLIED_PRICE maAppliedTo; // MA Applied To + int maFastLength; // Fast MA Length + int maSlowLength; // Slow MA Length + + // + // Presentation ... + bool showPV; // Show PV + bool showSAR; // Show Sar + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow + bool showFiboZone; // Show Fibo Zone + int startCalculationForLastBars; // Calculate Last n Bars + int sarArrowCode; // Parabolic Sar Arrow Code + int peakArrowCode; // Peaks Arrow Code + int valeArrowCode; // Vales Arrow Code + + // + // Constructor(s) ... + XOM1Inputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Calculations ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + upperMode = MODE_HIGH; // Peak Method + lowerMode = MODE_LOW; // Vale Method + upperZoneLevel = X_FIBO_LEVEL_618; // Upper Zone Level + lowerZoneLevel = X_FIBO_LEVEL_764; // Lower Zone Level + sarStep = 0.02; // SAR Step + sarMax = 0.2; // SAR Maximum + maMethod = MODE_EMA; // MA Method + maAppliedTo = PRICE_CLOSE; // MA Applied To + maFastLength = 7; // Fast MA Length + maSlowLength = 20; // Slow MA Length + + // + // Presentation ... + showPV = true; // Show PV + showSAR = true; // Show Sar + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow + showFiboZone = true; // Show Fibo Zone + startCalculationForLastBars = 1500; // Calculate Last n Bars + sarArrowCode = 159; // Parabolic Sar Arrow Code + peakArrowCode = 159; // Peaks Arrow Code + valeArrowCode = 159; // Vales Arrow Code + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showPV = false; + showSAR = false; + showMAFast = false; + showMASlow = false; + showFiboZone = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } +}; + +// +// Conditions ... +struct XOM1Conditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double maFastBuffer[]; + double maFastColorBuffer[]; + double maFastStateBuffer[]; + double maSlowBuffer[]; + double maSlowColorBuffer[]; + double maSlowStateBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboLowerBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + + // + // Conditions ... + + // + // Constructor ... + XOM1Conditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + SpecifiedClean(bars); + + // + SpecifiedClean(maFastBuffer); + SpecifiedClean(maFastColorBuffer); + SpecifiedClean(maFastStateBuffer); + SpecifiedClean(maSlowBuffer); + SpecifiedClean(maSlowColorBuffer); + SpecifiedClean(maSlowStateBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(sarColorBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(fiboUpperBuffer); + SpecifiedClean(fiboLowerBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + + // + // Conditions ... + + // + ArraySetAsSeries(bars, true); + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, 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); + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + } + + /** + * 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" // + ) + { + return ""; + } + + /** + * Retrieve Unique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } +}; + +// +// Class ... +class XCXOM1Helper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Buffers ... + double maFastBuffer[]; + double maFastColorBuffer[]; + double maFastStateBuffer[]; + double maSlowBuffer[]; + double maSlowColorBuffer[]; + double maSlowStateBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboLowerBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + + // + // Constructors ... + XCXOM1Helper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXOM1Helper() + { + } + + // + // Tools ... + + // + // Initialize Helper Cleass ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XOM1Inputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, 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.xom1", + "", // Calculation ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, + mInputs.upperZoneLevel, + mInputs.lowerZoneLevel, + mInputs.sarStep, + mInputs.sarMax, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.maFastLength, + mInputs.maSlowLength, + "", // Presentation ... + mInputs.showPV, + mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, + mInputs.showFiboZone, + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peakArrowCode, + mInputs.valeArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XOM1Inputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XOM1Inputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Tools ... + + // + void Update( + int barIndex // Bar Index + ) + { + Calculate(barIndex); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + XOM1Conditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + // Filling Bars ... + int barsCount = GetBars( + conditions.bars, + mSymbol, + mPeriod, + barIndex, + loopback // + ); + result = barsCount == loopback; + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // + // Buffers ... + + // + CopyMAFast( + zIndex, + loopback, + conditions.maFastBuffer // + ); + + // + CopyMAFastState( + zIndex, + loopback, + conditions.maFastStateBuffer // + ); + + // + CopyMASlow( + zIndex, + loopback, + conditions.maSlowBuffer // + ); + + // + CopyMASlowState( + zIndex, + loopback, + conditions.maSlowStateBuffer // + ); + + // + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyFiboUpper( + zIndex, + loopback, + conditions.fiboUpperBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + 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 ... + + // + return result; + } + + // + // Values Retrievers ... + + // + // Fast MA ... + + // + double GetMAFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maFastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maFastBuffer[barIndex]; + } + + // + int CopyMAFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maFastBuffer, + buffer, + forceClean + // + ); + } + + // + // Fast MA State ... + + // + double GetMAFastState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maFastStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maFastStateBuffer[barIndex]; + } + + // + int CopyMAFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maFastStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow MA ... + + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maSlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maSlowBuffer[barIndex]; + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maSlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow MA State ... + + // + double GetMASlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maSlowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maSlowStateBuffer[barIndex]; + } + + // + int CopyMASlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maSlowStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarStateBuffer[barIndex]; + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarStateBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Zone ... + + // + // FIBO Upper ... + + // + double GetFiboUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboUpperBuffer[barIndex]; + } + + // + int CopyFiboUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Lower ... + + // + double GetFiboLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLowerBuffer[barIndex]; + } + + // + int CopyFiboLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XOM1Inputs mInputs; // Inputs ... + + // + // Buffers ... + // Define in Public ... + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + XOM1_MA_FAST_LINE, + barIndex, + maxRequiredBars, + maFastBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_FAST_COLOR_LINE, + barIndex, + maxRequiredBars, + maFastColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_FAST_STATE_LINE, + barIndex, + maxRequiredBars, + maFastStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_SLOW_LINE, + barIndex, + maxRequiredBars, + maSlowBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_SLOW_COLOR_LINE, + barIndex, + maxRequiredBars, + maSlowColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_SLOW_STATE_LINE, + barIndex, + maxRequiredBars, + maSlowStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_SAR_COLOR_LINE, + barIndex, + maxRequiredBars, + sarColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_SAR_STATE_LINE, + barIndex, + maxRequiredBars, + sarStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_FINO_UPPER_LINE, + barIndex, + maxRequiredBars, + fiboUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_FINO_LOWER_LINE, + barIndex, + maxRequiredBars, + fiboLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_SC_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_SC_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MC_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MC_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_LC_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_LC_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_HC_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_HC_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + maFastBuffer, + maxAllowed // + ); + + // + CleanupArray( + maFastColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + maFastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLowerBuffer, + 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 // + ); + } +}; \ No newline at end of file diff --git a/BKPS/14040626/Indicators/x-saherelm.x121.xcatb.mq5 b/BKPS/14040626/Indicators/x-saherelm.x121.xcatb.mq5 new file mode 100644 index 0000000..81c63b5 --- /dev/null +++ b/BKPS/14040626/Indicators/x-saherelm.x121.xcatb.mq5 @@ -0,0 +1,2706 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCATB +// Description: Integrates All Requirements inside +// this indicator for analyse Markets to +// Detect Trigger Blocks ... +// +// - HK Bars; +// - ATR Band; +// - Signal Bars; +// - Parabolic Sar; +// - HK Signal Bars; +// - Peaks and Vales; +// - Peaks and Vales Goldens; +// - Trending Average Prices; +// +// - ATR; +// - RSI; +// - ADX; +// - DELTA; +// - VOLUME; +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCATB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCATB" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// Select Trending Cycle ... +// this Cycle Used for All Calculations ... +input ENUM_X_MARKET_CYCLES appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showKI = false; // Show KI +input bool showPV = false; // Show PV +input bool showPVGolden = false; // Show PV Golden +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showATRBand = false; // Show ATR Band +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +// Non Inputs ... +double sarStep = 0.02; // Step +double sarMax = 0.2; // Maximum +double rsiOBLevel = 70.0; // RSI OB Level +double rsiOSLevel = 30.0; // RSI OS Level +double adxThreshold = 25.0; // ADX Threshold +int kiLength = 144; // KI Length +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +double atrMultiplier = 1.5; // ATR Band Multiplier +bool showShortCycle = false; // Show Short Cycle Range +bool showMediumCycle = false; // Show Medium Cycle Range +bool showLongCycle = false; // Show Long Cycle Range +bool showHindCycle = false; // Show Hind Cycle Range +ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method +ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +ENUM_APPLIED_PRICE trendAppliedTo = PRICE_MEDIAN; // Trend Applied To +ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_EMA; // ATR Signalling Method +ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method +ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +// Plot: 18 +// Color: 4 +// Bar: 8 +// Data Buffer: 29 +#property indicator_buffers 50 +#property indicator_plots 19 + +// +// Plot Buffers ... + +// +// SAR ... + +// +#define sarBufferIndex 0 +#define sarBufferPlotIndex 0 +double sarBuffer[]; + +// +#define sarColorBufferIndex 1 +double sarColorBuffer[]; + +// +#property indicator_label1 "SAR" +#property indicator_type1 DRAW_COLOR_ARROW +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width1 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 2 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +// VALES ... + +// +#define valeBufferIndex 3 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 4 +#define peakGoldenBufferPlotIndex 3 +double peakGoldenBuffer[]; + +// +#property indicator_label4 "PEAK Golden" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 5 +#define valeGoldenBufferPlotIndex 4 +double valeGoldenBuffer[]; + +// +#property indicator_label5 "VALES Golden" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAqua +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 6 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +// +#property indicator_label6 "XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 7 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +// +#property indicator_label7 "XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// TREND ... + +// +#define trendBufferIndex 8 +#define trendBufferPlotIndex 7 +double trendBuffer[]; + +// +#define trendColorBufferIndex 9 +double trendColorBuffer[]; + +// +#property indicator_label8 "Trend" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style8 STYLE_SOLID +#property indicator_width8 2 + +// +// Signal Bar ... + +// +#define sBarOpenBufferIndex 10 +double sBarOpenBuffer[]; + +// +#define sBarHighBufferIndex 11 +double sBarHighBuffer[]; + +// +#define sBarLowBufferIndex 12 +double sBarLowBuffer[]; + +// +#define sBarCloseBufferIndex 13 +double sBarCloseBuffer[]; + +// +#define sBarColorBufferIndex 14 +double sBarColorBuffer[]; + +// +#define sBarBufferPlotIndex 8 +#property indicator_label9 "XSGB Open;XSGB High;XSGB Low;XSGB Close" +#property indicator_type9 DRAW_COLOR_CANDLES +#property indicator_color9 CLR_NONE, clrLime, clrRed + +// +// XHK SIGNAL ... + +// +#define hkSBarOpenBufferIndex 15 +double hkSBarOpenBuffer[]; + +// +#define hkSBarHighBufferIndex 16 +double hkSBarHighBuffer[]; + +// +#define hkSBarLowBufferIndex 17 +double hkSBarLowBuffer[]; + +// +#define hkSBarCloseBufferIndex 18 +double hkSBarCloseBuffer[]; + +// +#define hkSBarColorBufferIndex 19 +double hkSBarColorBuffer[]; + +// +#define hkSBarBufferPlotIndex 9 +#property indicator_label10 "XHKSGB Open;XHKSGB High;XHKSGB Low;XHKSGB Close" +#property indicator_type10 DRAW_COLOR_CANDLES +#property indicator_color10 CLR_NONE, clrAqua, clrMagenta + +// +// CYCLES Range ... + +// +// SHORT ... + +// +#define sHHBufferIndex 20 +#define sHHBufferPlotIndex 10 +double sHHBuffer[]; + +// +#property indicator_label11 "SH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define sLLBufferIndex 21 +#define sLLBufferPlotIndex 11 +double sLLBuffer[]; + +// +#property indicator_label12 "SL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 22 +#define mHHBufferPlotIndex 12 +double mHHBuffer[]; + +// +#property indicator_label13 "MH" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrIndigo +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define mLLBufferIndex 23 +#define mLLBufferPlotIndex 13 +double mLLBuffer[]; + +// +#property indicator_label14 "ML" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrIndigo +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// LONG ... + +// +#define lHHBufferIndex 24 +#define lHHBufferPlotIndex 14 +double lHHBuffer[]; + +// +#property indicator_label15 "LH" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGoldenrod +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define lLLBufferIndex 25 +#define lLLBufferPlotIndex 15 +double lLLBuffer[]; + +// +#property indicator_label16 "LL" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGoldenrod +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// HIND ... + +// +#define hHHBufferIndex 26 +#define hHHBufferPlotIndex 16 +double hHHBuffer[]; + +// +#property indicator_label17 "HH" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrBrown +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +#define hLLBufferIndex 27 +#define hLLBufferPlotIndex 17 +double hLLBuffer[]; + +// +#property indicator_label18 "HL" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrBrown +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// KI ... + +// +#define kiBufferIndex 28 +#define kiBufferPlotIndex 18 +double kiBuffer[]; + +// +#define kiColorBufferIndex 29 +double kiColorBuffer[]; + +// +#property indicator_label19 "KI" +#property indicator_type19 DRAW_COLOR_LINE +#property indicator_color19 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style19 STYLE_DASHDOTDOT +#property indicator_width19 2 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 29 + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 1 +double sarStateBuffer[]; + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 2 +double trendStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... + +// +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +// +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +// +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// HK ... + +// +#define openHKBufferIndex mLastBufferIndex + 16 +double openHKBuffer[]; + +// +#define highHKBufferIndex mLastBufferIndex + 17 +double highHKBuffer[]; + +// +#define lowHKBufferIndex mLastBufferIndex + 18 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex mLastBufferIndex + 19 +double closeHKBuffer[]; + +// +// KI ... + +// +#define kiStateBufferIndex mLastBufferIndex + 20 +double kiStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Applied Cycle ... +int mAppliedLength; +ENUM_TIMEFRAMES mAppliedPeriod = NULL; + +// +// Handlers ... +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + ReadBarStyle(); + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; + + // +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + ShowBars(); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + adxThreshold > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + // + IsValid(appliedCycle) && + // + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPVGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // ATR Band ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(sBarColorBuffer, true); + SetIndexBuffer(sBarColorBufferIndex, sBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(sBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(sBarOpenBuffer, true); + SetIndexBuffer(sBarOpenBufferIndex, sBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(sBarHighBuffer, true); + SetIndexBuffer(sBarHighBufferIndex, sBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(sBarLowBuffer, true); + SetIndexBuffer(sBarLowBufferIndex, sBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(sBarCloseBuffer, true); + SetIndexBuffer(sBarCloseBufferIndex, sBarCloseBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL Bar ... + + // + // HK Bars Color ... + ArraySetAsSeries(hkSBarColorBuffer, true); + SetIndexBuffer(hkSBarColorBufferIndex, hkSBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkSBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkSBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkSBarOpenBuffer, true); + SetIndexBuffer(hkSBarOpenBufferIndex, hkSBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkSBarHighBuffer, true); + SetIndexBuffer(hkSBarHighBufferIndex, hkSBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkSBarLowBuffer, true); + SetIndexBuffer(hkSBarLowBufferIndex, hkSBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkSBarCloseBuffer, true); + SetIndexBuffer(hkSBarCloseBufferIndex, hkSBarCloseBuffer, INDICATOR_DATA); + + // + // CYCLES ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // KI ... + + // + ArraySetAsSeries(kiBuffer, true); + SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiColorBuffer, true); + SetIndexBuffer(kiColorBufferIndex, kiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); + + // + // XHK ... + + // + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_CALCULATIONS); + + // + // KI ... + + // + ArraySetAsSeries(kiStateBuffer, true); + SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + // Selecte Applied Cycle ... + if (result) + { + // + switch (appliedCycle) + { + // + case X_MARKET_CYCLE_SHORT: + // + mAppliedLength = mSCLength; + mAppliedPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + // + mAppliedLength = mMCLength; + mAppliedPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + // + mAppliedLength = mLCLength; + mAppliedPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + // + mAppliedLength = mHCLength; + mAppliedPeriod = mHCPeriod; + break; + } + } + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + mAppliedLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + mAppliedLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + mAppliedLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mAppliedLength, + 0, + trendMode, + trendAppliedTo // + ); + result = trendHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + kiColorBuffer[barIndex] = hideColorIDX; + sarColorBuffer[barIndex] = hideColorIDX; + trendColorBuffer[barIndex] = hideColorIDX; + + // + atrUpperRawBuffer[barIndex] = emptyValue; + atrLowerRawBuffer[barIndex] = emptyValue; +} + +// +// Custom Handlers ... + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Cycle Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // KI ... + CalculateKI( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SAR ... + CalculateSAR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SBAR ... + CalculateSBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // HKBAR ... + CalculateHKBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // DELTA ... + CalculateDelta( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // TREND ... + CalculateTrend( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // VOLUME ... + CalculateVolume( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // ATR Band ... + CalculateATRBand( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +// +void CalculateKI( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + double iClose = close[barIndex]; + + // + // Calculate KI / Color ... + double lastKI = + isFirstBar + ? emptyValue + : kiBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiBuffer[barIndex] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKI + ? hideColorIDX + : bearishColorIDX; + } + kiStateBuffer[barIndex] = iKIState; + kiColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + +// +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; + + // + // GOLDEN ... + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + + // + peakGoldenBuffer[barIndex] = iPeakGold; + valeGoldenBuffer[barIndex] = iValeGold; + + // + iBar.Clean(); +} + +// +void CalculateSAR( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = low[barIndex]; + double iSar = sarBuffer[barIndex]; + + // + bool isBullish = iSar < iLow; + bool isBearish = iSar > iHigh; + + // + double iSarState = isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iSarColor = iSarState > 0 + ? bullishColorIDX + : iSarState < 0 + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = iSarState; + sarColorBuffer[barIndex] = showSar + ? iSarColor + : hideColorIDX; +} + +// +void CalculateSBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + open, + sBarOpenBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + close, + sBarCloseBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + double max = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + + // + sBarLowBuffer[barIndex] = min; + sBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + sBarOpenBuffer[barIndex] < sBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + sBarColorBuffer[barIndex] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; +} + +// +void CalculateHKBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[barIndex] + high[barIndex] + close[barIndex] + low[barIndex]) / 4; + double iHKHighValue = MathMax(high[barIndex], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[barIndex], MathMin(iHKOpenValue, iHKCloseValue)); + + // + // Raw HK Buffers ... + openHKBuffer[barIndex] = iHKOpenValue; + highHKBuffer[barIndex] = iHKHighValue; + lowHKBuffer[barIndex] = iHKLowValue; + closeHKBuffer[barIndex] = iHKCloseValue; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + openHKBuffer, + hkSBarOpenBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + closeHKBuffer, + hkSBarCloseBuffer, + hkSignalBarMethod // + ); + + // + double min = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + double max = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + + // + hkSBarLowBuffer[barIndex] = min; + hkSBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + hkSBarColorBuffer[barIndex] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; +} + +// +void CalculateDelta( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[barIndex] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); +} + +// +void CalculateTrend( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iClose = close[barIndex]; + double iTrend = trendBuffer[barIndex]; + + // + bool isBullish = iTrend < iLow; + bool isBearish = iTrend > iHigh; + + // + double iTrendState = + isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iTrendColor = + iTrendState > 0 + ? bullishColorIDX + : iTrendState < 0 + ? bearishColorIDX + : neuturalColorIDX; + trendStateBuffer[barIndex] = iTrendState; + trendColorBuffer[barIndex] = showTrend + ? iTrendColor + : hideColorIDX; +} + +// +void CalculateVolume( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[barIndex] = iBullishVolume; + bearishVolumeBuffer[barIndex] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); +} + +// +void CalculateATRBand( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iATR = atrBuffer[barIndex]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[barIndex] = iATRUpper; + atrLowerRawBuffer[barIndex] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[barIndex] = iATRUpper; + atrLowerBuffer[barIndex] = iATRLower; + } +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Indicators/x-saherelm.x121.xcatb.v1.mq5 b/BKPS/14040626/Indicators/x-saherelm.x121.xcatb.v1.mq5 new file mode 100644 index 0000000..73ac97a --- /dev/null +++ b/BKPS/14040626/Indicators/x-saherelm.x121.xcatb.v1.mq5 @@ -0,0 +1,5498 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCATB +// Description: Integrates All Requirements inside +// this indicator for analyse Markets to +// Detect Trigger Blocks ... +// +// - HK Bars; +// - ATR Band; +// - Signal Bars; +// - Parabolic Sar; +// - HK Signal Bars; +// - Peaks and Vales; +// - Peaks and Vales Goldens; +// - Trending Average Prices; +// +// - ATR; +// - RSI; +// - ADX; +// - DELTA; +// - VOLUME; +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCATB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCATB" + +// +// Imports ... +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// Select Trending Cycle ... +// this Cycle Used for All Calculations ... +input ENUM_X_MARKET_CYCLES appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showKI = false; // Show KI +input bool showPV = false; // Show PV +input bool showPVGolden = false; // Show PV Golden +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showATRBand = false; // Show ATR Band +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +// Non Inputs ... +double sarStep = 0.02; // Step +double sarMax = 0.2; // Maximum +double rsiOBLevel = 70.0; // RSI OB Level +double rsiOSLevel = 30.0; // RSI OS Level +double adxThreshold = 25.0; // ADX Threshold +int kiLength = 144; // KI Length +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +double atrMultiplier = 1.5; // ATR Band Multiplier +bool showShortCycle = false; // Show Short Cycle Range +bool showMediumCycle = false; // Show Medium Cycle Range +bool showLongCycle = false; // Show Long Cycle Range +bool showHindCycle = false; // Show Hind Cycle Range +ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method +ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +ENUM_APPLIED_PRICE trendAppliedTo = PRICE_MEDIAN; // Trend Applied To +ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_EMA; // ATR Signalling Method +ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method +ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +// Plot: 18 +// Color: 4 +// Bar: 8 +// Data Buffer: 29 +#property indicator_buffers 50 +#property indicator_plots 19 + +// +// Plot Buffers ... + +// +// SAR ... + +// +#define sarBufferIndex 0 +#define sarBufferPlotIndex 0 +double sarBuffer[]; + +// +#define sarColorBufferIndex 1 +double sarColorBuffer[]; + +// +#property indicator_label1 "SAR" +#property indicator_type1 DRAW_COLOR_ARROW +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width1 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 2 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +// VALES ... + +// +#define valeBufferIndex 3 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 4 +#define peakGoldenBufferPlotIndex 3 +double peakGoldenBuffer[]; + +// +#property indicator_label4 "PEAK Golden" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 5 +#define valeGoldenBufferPlotIndex 4 +double valeGoldenBuffer[]; + +// +#property indicator_label5 "VALES Golden" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAqua +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 6 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +// +#property indicator_label6 "XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 7 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +// +#property indicator_label7 "XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// TREND ... + +// +#define trendBufferIndex 8 +#define trendBufferPlotIndex 7 +double trendBuffer[]; + +// +#define trendColorBufferIndex 9 +double trendColorBuffer[]; + +// +#property indicator_label8 "Trend" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style8 STYLE_SOLID +#property indicator_width8 2 + +// +// Signal Bar ... + +// +#define sBarOpenBufferIndex 10 +double sBarOpenBuffer[]; + +// +#define sBarHighBufferIndex 11 +double sBarHighBuffer[]; + +// +#define sBarLowBufferIndex 12 +double sBarLowBuffer[]; + +// +#define sBarCloseBufferIndex 13 +double sBarCloseBuffer[]; + +// +#define sBarColorBufferIndex 14 +double sBarColorBuffer[]; + +// +#define sBarBufferPlotIndex 8 +#property indicator_label9 "XSGB Open;XSGB High;XSGB Low;XSGB Close" +#property indicator_type9 DRAW_COLOR_CANDLES +#property indicator_color9 CLR_NONE, clrLime, clrRed + +// +// XHK SIGNAL ... + +// +#define hkSBarOpenBufferIndex 15 +double hkSBarOpenBuffer[]; + +// +#define hkSBarHighBufferIndex 16 +double hkSBarHighBuffer[]; + +// +#define hkSBarLowBufferIndex 17 +double hkSBarLowBuffer[]; + +// +#define hkSBarCloseBufferIndex 18 +double hkSBarCloseBuffer[]; + +// +#define hkSBarColorBufferIndex 19 +double hkSBarColorBuffer[]; + +// +#define hkSBarBufferPlotIndex 9 +#property indicator_label10 "XHKSGB Open;XHKSGB High;XHKSGB Low;XHKSGB Close" +#property indicator_type10 DRAW_COLOR_CANDLES +#property indicator_color10 CLR_NONE, clrAqua, clrMagenta + +// +// CYCLES Range ... + +// +// SHORT ... + +// +#define sHHBufferIndex 20 +#define sHHBufferPlotIndex 10 +double sHHBuffer[]; + +// +#property indicator_label11 "SH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define sLLBufferIndex 21 +#define sLLBufferPlotIndex 11 +double sLLBuffer[]; + +// +#property indicator_label12 "SL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 22 +#define mHHBufferPlotIndex 12 +double mHHBuffer[]; + +// +#property indicator_label13 "MH" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrIndigo +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define mLLBufferIndex 23 +#define mLLBufferPlotIndex 13 +double mLLBuffer[]; + +// +#property indicator_label14 "ML" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrIndigo +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// LONG ... + +// +#define lHHBufferIndex 24 +#define lHHBufferPlotIndex 14 +double lHHBuffer[]; + +// +#property indicator_label15 "LH" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGoldenrod +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define lLLBufferIndex 25 +#define lLLBufferPlotIndex 15 +double lLLBuffer[]; + +// +#property indicator_label16 "LL" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGoldenrod +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// HIND ... + +// +#define hHHBufferIndex 26 +#define hHHBufferPlotIndex 16 +double hHHBuffer[]; + +// +#property indicator_label17 "HH" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrBrown +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +#define hLLBufferIndex 27 +#define hLLBufferPlotIndex 17 +double hLLBuffer[]; + +// +#property indicator_label18 "HL" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrBrown +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// KI ... + +// +#define kiBufferIndex 28 +#define kiBufferPlotIndex 18 +double kiBuffer[]; + +// +#define kiColorBufferIndex 29 +double kiColorBuffer[]; + +// +#property indicator_label19 "KI" +#property indicator_type19 DRAW_COLOR_LINE +#property indicator_color19 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style19 STYLE_DASHDOTDOT +#property indicator_width19 2 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 29 + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 1 +double sarStateBuffer[]; + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 2 +double trendStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... + +// +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +// +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +// +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// HK ... + +// +#define openHKBufferIndex mLastBufferIndex + 16 +double openHKBuffer[]; + +// +#define highHKBufferIndex mLastBufferIndex + 17 +double highHKBuffer[]; + +// +#define lowHKBufferIndex mLastBufferIndex + 18 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex mLastBufferIndex + 19 +double closeHKBuffer[]; + +// +// KI ... + +// +#define kiStateBufferIndex mLastBufferIndex + 20 +double kiStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Applied Cycle ... +int mAppliedLength; +ENUM_TIMEFRAMES mAppliedPeriod = NULL; + +// +// Handlers ... +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +CArrayObj mObjects; +XCPOIDrawer *mDrawer; +XCBarAnalyser *mBarAnalyser; + +// +// Conditions Variables ... + +// +// Temparory ... +int mCount = 0; +XSignal mSignal; +bool mHas = false; +XBoxZone mSignalBox; +ENUM_X_DIRECTION mDir; +bool mHasSignal = false; +bool mIsBullish = false; +bool mIsBearish = false; +XDirectionShift mDirShift; +string mArrowNamePrefix = NULL; + +// +// Signals ... + +// +bool mDrawSignals = false; +bool mDrawSignalBoxes = false; +bool mDrawSignalArrows = true; +bool mDrawSignalBoxAtLines = false; + +// +int _bullishArrowCode = 225; +int _bearishArrowCode = 226; + +// +color _bullishArrowColor = clrLime; +color _bearishArrowColor = clrRed; + +// +XPOIStyle mBullishSignalBoxStyle; +XPOIStyle mBearishSignalBoxStyle; + +// +ENUM_ARROW_ANCHOR mBullishAnchor = ANCHOR_TOP; +ENUM_ARROW_ANCHOR mBearishAnchor = ANCHOR_BOTTOM; + +// +// POI(s) ... + +// +// Liquidities ... +bool mDrawLiquidities = false; +bool mDetectLiquidities = true; +XBoxZone mBullishLiquidities[]; +XBoxZone mBearishLiquidities[]; +XPOIStyle mBullishLiquidityStyle; +XPOIStyle mBearishLiquidityStyle; + +// +// Range Breakes ... +bool mDrawRangeBreakes = false; +bool mDetectRangeBreakes = true; +XBoxZone mBullishRangeBreakes[]; +XBoxZone mBearishRangeBreakes[]; +XPOIStyle mBullishRangeBreakStyle; +XPOIStyle mBearishRangeBreakStyle; + +// +// Counters ... + +// +int mSameSBCount = 0; +int mSameBullishSBCount = 0; +int mSameBearishSBCount = 0; + +// +int mSameKICount = 0; +int mSameBullishKICount = 0; +int mSameBearishKICount = 0; + +// +int mSameHKSCount = 0; +int mSameBullishHKSCount = 0; +int mSameBearishHKSCount = 0; + +// +int mSameSarCount = 0; +int mSameBullishSarCount = 0; +int mSameBearishSarCount = 0; + +// +int mSameTrendCount = 0; +int mSameBullishTrendCount = 0; +int mSameBearishTrendCount = 0; + +// +int mSamePeakCount = 0; +int mSameValeCount = 0; +int mSamePeakGoldenCount = 0; +int mSameValeGoldenCount = 0; + +// +double mSamePeakGoldenMin = 0; +double mSamePeakGoldenMax = 0; +double mSameValeGoldenMin = 0; +double mSameValeGoldenMax = 0; + +// +// Direction Shift ... + +// +XDirectionShift mBullishKIChanges[]; +XDirectionShift mBearishKIChanges[]; + +// +XDirectionShift mBullishSBChanges[]; +XDirectionShift mBearishSBChanges[]; + +// +XDirectionShift mBullishHKSChanges[]; +XDirectionShift mBearishHKSChanges[]; + +// +XDirectionShift mBullishSarChanges[]; +XDirectionShift mBearishSarChanges[]; + +// +XDirectionShift mBullishTrendChanges[]; +XDirectionShift mBearishTrendChanges[]; + +// +// Liquidities ... + +// +bool isLiquidity = false; +bool isBullishLiquidity = false; +bool isBearishLiquidity = false; + +// +// Trigger Bars Conditions ... + +// +bool isTriggerBarCond1 = false; +bool isTriggerBarCond1Bullish = false; +bool isTriggerBarCond1Bearish = false; + +// +bool isTriggerBarCond2 = false; +bool isTriggerBarCond2Bullish = false; +bool isTriggerBarCond2Bearish = false; + +// +bool isTriggerBarCond3 = false; +bool isTriggerBarCond3Bullish = false; +bool isTriggerBarCond3Bearish = false; + +// +bool isTriggerBarCond4 = false; +bool isTriggerBarCond4Bullish = false; +bool isTriggerBarCond4Bearish = false; + +// +bool isTriggerBarCond5 = false; +bool isTriggerBarCond5Bullish = false; +bool isTriggerBarCond5Bearish = false; + +// +bool isTriggerBarCond6 = false; +bool isTriggerBarCond6Bullish = false; +bool isTriggerBarCond6Bearish = false; + +// +bool isTriggerBarCond7 = false; +bool isTriggerBarCond7Bullish = false; +bool isTriggerBarCond7Bearish = false; + +// +// Summarizing Trigger Bar ... +bool isTriggerBar = false; +bool isTriggerBarBullish = false; +bool isTriggerBarBearish = false; + +// +// XPV ... + +// +bool isSamePeak = false; +bool isSamePeakP = false; + +// +bool isSameVale = false; +bool isSameValeP = false; + +// +bool isPeakOverLast = false; +bool isPeakUnderLast = false; + +// +bool isValeOverLast = false; +bool isValeUnderLast = false; + +// +bool isSamePeakOverLast = false; +bool isSamePeakUnderLast = false; + +// +bool isSameValeOverLast = false; +bool isSameValeUnderLast = false; + +// +bool isSamePeakGolden = false; +bool isSamePeakGoldenP = false; + +// +bool isSameValeGolden = false; +bool isSameValeGoldenP = false; + +// +bool isPeakGoldenOverLast = false; +bool isPeakGoldenUnderLast = false; + +// +bool isValeGoldenOverLast = false; +bool isValeGoldenUnderLast = false; + +// +bool isSamePeakGoldenOverLast = false; +bool isSamePeakGoldenUnderLast = false; + +// +bool isSameValeGoldenOverLast = false; +bool isSameValeGoldenUnderLast = false; + +// +// XSAR ... + +// +bool isSarBullish = false; +bool isSarBullishP = false; + +// +bool isSarBearish = false; +bool isSarBearishP = false; + +// +bool isSarSwitchedToBullish = false; +bool isSarSwitchedToBearish = false; + +// +bool isBullishSarBreakedLast = false; +bool isBearishSarBreakedLast = false; + +// +// XSB ... + +// +double mSBMax = 0; +double mSBMin = 0; + +// +double mSBPMax = 0; +double mSBPMin = 0; + +// +bool isSBBullish = false; +bool isSBBullishP = false; + +// +bool isSBBearish = false; +bool isSBBearishP = false; + +// +bool isSBSwitchedToBullish = false; +bool isSBSwitchedToBearish = false; + +// +bool isBullishSBBreakedLast = false; +bool isBearishSBBreakedLast = false; + +// +// XHKS ... + +// +double mHKSMax = 0; +double mHKSMin = 0; + +// +double mHKSPMax = 0; +double mHKSPMin = 0; + +// +bool isHKSBullish = false; +bool isHKSBullishP = false; + +// +bool isHKSBearish = false; +bool isHKSBearishP = false; + +// +bool isHKSSwitchedToBullish = false; +bool isHKSSwitchedToBearish = false; + +// +bool isBullishHKSBreakedLast = false; +bool isBearishHKSBreakedLast = false; + +// +// XKI ... + +// +bool isKIBullish = false; +bool isKIBullishP = false; + +// +bool isKIBearish = false; +bool isKIBearishP = false; + +// +bool isSameKI = false; +bool isSameBullishKI = false; +bool isSameBearishKI = false; + +// +bool isKISwitchedToBullish = false; +bool isKISwitchedToBearish = false; + +// +bool isBullishKIBreakedLast = false; +bool isBearishKIBreakedLast = false; + +// +// XTREND ... + +// +bool isTrendBullish = false; +bool isTrendBullishP = false; + +// +bool isTrendBearish = false; +bool isTrendBearishP = false; + +// +bool isTrendSwitchedToBullish = false; +bool isTrendSwitchedToBearish = false; + +// +bool isBullishTrendBreakedLast = false; +bool isBearishTrendBreakedLast = false; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + ReadBarStyle(); + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initial Requirements ... + mDrawer = new XCPOIDrawer(); + mBarAnalyser = new XCBarAnalyser(); + + // + // Preparing Styles ... + + // + // Signals ... + + // + // Bullish ... + mBullishSignalBoxStyle.width = 1; + mBullishSignalBoxStyle.clr = clrAqua; + mBullishSignalBoxStyle.style = STYLE_DOT; + + // + // Bearish ... + mBearishSignalBoxStyle.width = 1; + mBearishSignalBoxStyle.style = STYLE_DOT; + mBearishSignalBoxStyle.clr = clrMagenta; + + // + // Liquidities ... + + // + // Bullish ... + mBullishLiquidityStyle.width = 1; + mBullishLiquidityStyle.clr = clrLime; + + // + // Bearish ... + mBearishLiquidityStyle.width = 1; + mBearishLiquidityStyle.clr = clrRed; + + // + // Range Breakes ... + + // + // Bullish ... + mBullishRangeBreakStyle.width = 1; + mBullishRangeBreakStyle.clr = clrAqua; + + // + // Bearish ... + mBearishRangeBreakStyle.width = 1; + mBearishRangeBreakStyle.clr = clrMagenta; + + // + // Init Succeed ... + return INIT_SUCCEEDED; + + // +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + ShowBars(); + + // + // De Initial Requirements ... + mObjects.Clear(); + + // + delete mDrawer; + ZeroMemory(mDrawer); + + delete mBarAnalyser; + ZeroMemory(mBarAnalyser); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); + + // + mSignal.Clean(); + mDirShift.Clean(); + mSignalBox.Clean(); + + // + Clean(mBullishKIChanges); + Clean(mBearishKIChanges); + Clean(mBullishSBChanges); + Clean(mBearishSBChanges); + Clean(mBullishHKSChanges); + Clean(mBearishHKSChanges); + Clean(mBullishSarChanges); + Clean(mBearishSarChanges); + Clean(mBullishTrendChanges); + Clean(mBearishTrendChanges); + + // + Clean(mBullishLiquidities); + Clean(mBearishLiquidities); + Clean(mBullishRangeBreakes); + Clean(mBearishRangeBreakes); + + // + mBullishSignalBoxStyle.Clean(); + mBearishSignalBoxStyle.Clean(); + + // + mBullishLiquidityStyle.Clean(); + mBearishLiquidityStyle.Clean(); + mBullishRangeBreakStyle.Clean(); + mBearishRangeBreakStyle.Clean(); + + // +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + if (prev_calculated == 0) + { + // + string message = "History Started ..."; + Print(message); + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + adxThreshold > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + // + IsValid(appliedCycle) && + // + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPVGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // ATR Band ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(sBarColorBuffer, true); + SetIndexBuffer(sBarColorBufferIndex, sBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(sBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(sBarOpenBuffer, true); + SetIndexBuffer(sBarOpenBufferIndex, sBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(sBarHighBuffer, true); + SetIndexBuffer(sBarHighBufferIndex, sBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(sBarLowBuffer, true); + SetIndexBuffer(sBarLowBufferIndex, sBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(sBarCloseBuffer, true); + SetIndexBuffer(sBarCloseBufferIndex, sBarCloseBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL Bar ... + + // + // HK Bars Color ... + ArraySetAsSeries(hkSBarColorBuffer, true); + SetIndexBuffer(hkSBarColorBufferIndex, hkSBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkSBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkSBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkSBarOpenBuffer, true); + SetIndexBuffer(hkSBarOpenBufferIndex, hkSBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkSBarHighBuffer, true); + SetIndexBuffer(hkSBarHighBufferIndex, hkSBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkSBarLowBuffer, true); + SetIndexBuffer(hkSBarLowBufferIndex, hkSBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkSBarCloseBuffer, true); + SetIndexBuffer(hkSBarCloseBufferIndex, hkSBarCloseBuffer, INDICATOR_DATA); + + // + // CYCLES ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // KI ... + + // + ArraySetAsSeries(kiBuffer, true); + SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiColorBuffer, true); + SetIndexBuffer(kiColorBufferIndex, kiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); + + // + // XHK ... + + // + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_CALCULATIONS); + + // + // KI ... + + // + ArraySetAsSeries(kiStateBuffer, true); + SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + // Selecte Applied Cycle ... + if (result) + { + // + switch (appliedCycle) + { + // + case X_MARKET_CYCLE_SHORT: + // + mAppliedLength = mSCLength; + mAppliedPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + // + mAppliedLength = mMCLength; + mAppliedPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + // + mAppliedLength = mLCLength; + mAppliedPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + // + mAppliedLength = mHCLength; + mAppliedPeriod = mHCPeriod; + break; + } + } + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + mAppliedLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + mAppliedLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + mAppliedLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mAppliedLength, + 0, + trendMode, + trendAppliedTo // + ); + result = trendHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + kiColorBuffer[barIndex] = hideColorIDX; + sarColorBuffer[barIndex] = hideColorIDX; + trendColorBuffer[barIndex] = hideColorIDX; + + // + atrUpperRawBuffer[barIndex] = emptyValue; + atrLowerRawBuffer[barIndex] = emptyValue; +} + +// +// Value Calculators ... + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Cycle Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // KI ... + CalculateKI( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SAR ... + CalculateSAR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SBAR ... + CalculateSBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // HKBAR ... + CalculateHKBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // DELTA ... + CalculateDelta( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // TREND ... + CalculateTrend( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // VOLUME ... + CalculateVolume( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // ATR Band ... + CalculateATRBand( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Handling Process ... + + // + // Prepare Market Conditions ... + PrepareMarketConditions( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Detecting POI(s) ... + DetectPOIs( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Validating ... + ValidatePOIs( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Drawing ... + DrawPOIs( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Do Process on Bars ... + DoProcess( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +/** + * Calculate Cycle Ranges Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +/** + * Calculate KI Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateKI( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + double iClose = close[barIndex]; + + // + // Calculate KI / Color ... + double lastKI = + isFirstBar + ? emptyValue + : kiBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiBuffer[barIndex] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKI + ? hideColorIDX + : bearishColorIDX; + } + kiStateBuffer[barIndex] = iKIState; + kiColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + +/** + * Calculate Peaks and Vales Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; + + // + // GOLDEN ... + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + + // + peakGoldenBuffer[barIndex] = iPeakGold; + valeGoldenBuffer[barIndex] = iValeGold; + + // + iBar.Clean(); +} + +/** + * Calculate PSar Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateSAR( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = low[barIndex]; + double iSar = sarBuffer[barIndex]; + + // + bool isBullish = iSar < iLow; + bool isBearish = iSar > iHigh; + + // + double iSarState = isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iSarColor = iSarState > 0 + ? bullishColorIDX + : iSarState < 0 + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = iSarState; + sarColorBuffer[barIndex] = showSar + ? iSarColor + : hideColorIDX; +} + +/** + * Calculate Signal Bar Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateSBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + open, + sBarOpenBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + close, + sBarCloseBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + double max = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + + // + sBarLowBuffer[barIndex] = min; + sBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + sBarOpenBuffer[barIndex] < sBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + sBarColorBuffer[barIndex] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; +} + +/** + * Calculate HK and HK Signal Bars Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateHKBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[barIndex] + high[barIndex] + close[barIndex] + low[barIndex]) / 4; + double iHKHighValue = MathMax(high[barIndex], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[barIndex], MathMin(iHKOpenValue, iHKCloseValue)); + + // + // Raw HK Buffers ... + openHKBuffer[barIndex] = iHKOpenValue; + highHKBuffer[barIndex] = iHKHighValue; + lowHKBuffer[barIndex] = iHKLowValue; + closeHKBuffer[barIndex] = iHKCloseValue; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + openHKBuffer, + hkSBarOpenBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + closeHKBuffer, + hkSBarCloseBuffer, + hkSignalBarMethod // + ); + + // + double min = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + double max = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + + // + hkSBarLowBuffer[barIndex] = min; + hkSBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + hkSBarColorBuffer[barIndex] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; +} + +/** + * Calculate Delta Oscillator Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateDelta( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[barIndex] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); +} + +/** + * Calculate Trend Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateTrend( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iClose = close[barIndex]; + double iTrend = trendBuffer[barIndex]; + + // + bool isBullish = iTrend < iLow; + bool isBearish = iTrend > iHigh; + + // + double iTrendState = + isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iTrendColor = + iTrendState > 0 + ? bullishColorIDX + : iTrendState < 0 + ? bearishColorIDX + : neuturalColorIDX; + trendStateBuffer[barIndex] = iTrendState; + trendColorBuffer[barIndex] = showTrend + ? iTrendColor + : hideColorIDX; +} + +/** + * Calculate Volume Oscillators Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateVolume( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[barIndex] = iBullishVolume; + bearishVolumeBuffer[barIndex] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); +} + +/** + * Calculate ATR Band Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateATRBand( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iATR = atrBuffer[barIndex]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[barIndex] = iATRUpper; + atrLowerRawBuffer[barIndex] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[barIndex] = iATRUpper; + atrLowerBuffer[barIndex] = iATRLower; + } +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// +// +// + +/** + * Reading Bar Style and Store it ... + */ +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +/** + * Show Bars ... + */ +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +/** + * Hide Bars ... + */ +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// +// Process Handlers ... +// + +/** + * Prepare Market Conditions ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void PrepareMarketConditions( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Some Requirements ... + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Recieve Bar ... + XOHCL iBar; + XOHCL iPBar; + mHas = iBar.Init( + _Symbol, + _Period, + barIndex + // + ); + mHas = + mHas && + iBar.GetPreviousBar(iPBar); + if (!mHas) + { + return; + } + + // + int cIndex = barIndex; + int pIndex = barIndex + 1; + int p2Index = barIndex + 2; + int p3Index = barIndex + 3; + + // + // Check Required Bars Passed ... + mHas = p3Index <= maxBarIndex; + if (!mHas) + { + return; + } + + // + // Start Preparing Conditions ... + + // + // Liquidities ... + + // + isLiquidity = + mBarAnalyser + .IsRejected( + iBar, + mDir, + true, + true // + ); + isBullishLiquidity = + isLiquidity && + IsBullish(mDir); + isBearishLiquidity = + isLiquidity && + IsBearish(mDir); + + // + // Trigger Bars Conditions ... + + // + // Cond 1 ... + isTriggerBarCond1 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + true, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + isTriggerBarCond1Bullish = + isTriggerBarCond1 && + IsBullish(mDir); + isTriggerBarCond1Bearish = + isTriggerBarCond1 && + IsBearish(mDir); + if (isTriggerBarCond1) + { + mArrowNamePrefix += "1"; + } + + // + // Cond 2 ... + isTriggerBarCond2 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + false, // Cond 1 ... + true, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + isTriggerBarCond2Bullish = + isTriggerBarCond2 && + IsBullish(mDir); + isTriggerBarCond2Bearish = + isTriggerBarCond2 && + IsBearish(mDir); + if (isTriggerBarCond2) + { + mArrowNamePrefix += ",2"; + } + + // + // Cond 3 ... + isTriggerBarCond3 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + false, // Cond 1 ... + false, // Cond 2 ... + true, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + isTriggerBarCond3Bullish = + isTriggerBarCond3 && + IsBullish(mDir); + isTriggerBarCond3Bearish = + isTriggerBarCond3 && + IsBearish(mDir); + if (isTriggerBarCond3) + { + mArrowNamePrefix += ",3"; + } + + // + // Cond 4 ... + isTriggerBarCond4 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + true, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + isTriggerBarCond4Bullish = + isTriggerBarCond4 && + IsBullish(mDir); + isTriggerBarCond4Bearish = + isTriggerBarCond4 && + IsBearish(mDir); + if (isTriggerBarCond4) + { + mArrowNamePrefix += ",4"; + } + + // + // Cond 5 ... + isTriggerBarCond5 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + true, // Cond 5 ... + false, // Cond 6 ... + false // Cond 7 ... + ); + isTriggerBarCond5Bullish = + isTriggerBarCond5 && + IsBullish(mDir); + isTriggerBarCond5Bearish = + isTriggerBarCond5 && + IsBearish(mDir); + if (isTriggerBarCond5) + { + mArrowNamePrefix += ",5"; + } + + // + // Cond 6 ... + isTriggerBarCond6 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + true, // Cond 6 ... + false // Cond 7 ... + ); + isTriggerBarCond6Bullish = + isTriggerBarCond6 && + IsBullish(mDir); + isTriggerBarCond6Bearish = + isTriggerBarCond6 && + IsBearish(mDir); + if (isTriggerBarCond6) + { + mArrowNamePrefix += ",6"; + } + + // + // Cond 7 ... + isTriggerBarCond7 = + mBarAnalyser + .IsValidForTrigger( + iPBar, + mDir, + false, // Cond 1 ... + false, // Cond 2 ... + false, // Cond 3 ... + false, // Cond 4 ... + false, // Cond 5 ... + false, // Cond 6 ... + true // Cond 7 ... + ); + isTriggerBarCond7Bullish = + isTriggerBarCond7 && + IsBullish(mDir); + isTriggerBarCond7Bearish = + isTriggerBarCond7 && + IsBearish(mDir); + if (isTriggerBarCond7) + { + mArrowNamePrefix += ",7"; + } + + // + // Summarizing Trigger Bar ... + + // + isTriggerBar = + isTriggerBarCond1 || + isTriggerBarCond2 || + isTriggerBarCond3 || + isTriggerBarCond4 || + isTriggerBarCond5 || + isTriggerBarCond6 || + isTriggerBarCond7; + + // + isTriggerBarBullish = + isTriggerBarCond1Bullish || + isTriggerBarCond2Bullish || + isTriggerBarCond3Bullish || + isTriggerBarCond4Bullish || + isTriggerBarCond5Bullish || + isTriggerBarCond6Bullish || + isTriggerBarCond7Bullish; + + // + isTriggerBarBearish = + isTriggerBarCond1Bearish || + isTriggerBarCond2Bearish || + isTriggerBarCond3Bearish || + isTriggerBarCond4Bearish || + isTriggerBarCond5Bearish || + isTriggerBarCond6Bearish || + isTriggerBarCond7Bearish; + + // + // Resetting Counters Based on Conditions ... + + // + // XPV ... + + // + if (!isSamePeak) + { + // + mSamePeakCount = 0; + mSamePeakGoldenMin = 0; + mSamePeakGoldenMax = 0; + } + + // + if (!isSameVale) + { + // + mSameValeCount = 0; + mSameValeGoldenMin = 0; + mSameValeGoldenMax = 0; + } + + // + if (!isSamePeakGolden) + { + mSamePeakGoldenCount = 0; + } + + // + if (!isSameValeGolden) + { + mSameValeGoldenCount = 0; + } + + // + // XKI ... + + // + if (!isSameKI) + { + mSameKICount = 0; + } + + // + if (!isSameBullishKI) + { + mSameBullishKICount = 0; + } + + // + if (!isSameBearishKI) + { + mSameBearishKICount = 0; + } + + // + // XSB ... + + // + if (isSBSwitchedToBullish) + { + // + mSameSBCount = 0; + mSameBullishSBCount = 0; + } + + // + if (isSBSwitchedToBearish) + { + // + mSameSBCount = 0; + mSameBearishSBCount = 0; + } + + // + // XSAR ... + + // + if (isSarSwitchedToBullish) + { + // + mSameSarCount = 0; + mSameBullishSarCount = 0; + } + + // + if (isSarSwitchedToBearish) + { + // + mSameSarCount = 0; + mSameBearishSarCount = 0; + } + + // + // XHKS ... + + // + if (isHKSSwitchedToBullish) + { + // + mSameHKSCount = 0; + mSameBullishHKSCount = 0; + } + + // + if (isHKSSwitchedToBearish) + { + // + mSameHKSCount = 0; + mSameBearishHKSCount = 0; + } + + // + // XTREND ... + + // + if (isTrendSwitchedToBullish) + { + // + mSameTrendCount = 0; + mSameBullishTrendCount = 0; + } + + // + if (isTrendSwitchedToBearish) + { + // + mSameTrendCount = 0; + mSameBearishTrendCount = 0; + } + + // + // Preparing Conditions ... + + // + // XPV ... + + // + isSamePeak = peakBuffer[pIndex] == peakBuffer[p2Index]; + isSamePeakP = peakBuffer[p2Index] == peakBuffer[p3Index]; + + // + isSameVale = valeBuffer[pIndex] == valeBuffer[p2Index]; + isSameValeP = valeBuffer[p2Index] == valeBuffer[p3Index]; + + // + isPeakOverLast = peakBuffer[pIndex] > peakBuffer[p2Index]; + isPeakUnderLast = peakBuffer[pIndex] < peakBuffer[p2Index]; + + // + isValeOverLast = valeBuffer[pIndex] > valeBuffer[p2Index]; + isValeUnderLast = valeBuffer[pIndex] < valeBuffer[p2Index]; + + // + isSamePeakOverLast = + isSamePeakP && + isPeakOverLast; + isSamePeakUnderLast = + isSamePeakP && + isPeakUnderLast; + + // + isSameValeOverLast = + isSameValeP && + isValeOverLast; + isSameValeUnderLast = + isSameValeP && + isValeUnderLast; + + // + isSamePeakGolden = peakGoldenBuffer[pIndex] == peakGoldenBuffer[p2Index]; + isSamePeakGoldenP = peakGoldenBuffer[p2Index] == peakGoldenBuffer[p3Index]; + + // + isSameValeGolden = valeGoldenBuffer[pIndex] == valeGoldenBuffer[p2Index]; + isSameValeGoldenP = valeGoldenBuffer[p2Index] == valeGoldenBuffer[p3Index]; + + // + isPeakGoldenOverLast = peakGoldenBuffer[pIndex] > peakGoldenBuffer[p2Index]; + isPeakGoldenUnderLast = peakGoldenBuffer[pIndex] < peakGoldenBuffer[p2Index]; + + // + isValeGoldenOverLast = valeGoldenBuffer[pIndex] > valeGoldenBuffer[p2Index]; + isValeGoldenUnderLast = valeGoldenBuffer[pIndex] < valeGoldenBuffer[p2Index]; + + // + isSamePeakGoldenOverLast = + isSamePeakGoldenP && + isPeakGoldenOverLast; + isSamePeakGoldenUnderLast = + isSamePeakGoldenP && + isPeakGoldenUnderLast; + + // + isSameValeGoldenOverLast = + isSameValeGoldenP && + isValeGoldenOverLast; + isSameValeGoldenUnderLast = + isSameValeGoldenP && + isSameValeGoldenUnderLast; + + // + // XSAR ... + + // + isSarBullish = sarStateBuffer[pIndex] > 0; + isSarBullishP = sarStateBuffer[p2Index] > 0; + + // + isSarBearish = sarStateBuffer[pIndex] < 0; + isSarBearishP = sarStateBuffer[p2Index] < 0; + + // + isSarSwitchedToBullish = + isSarBullish && + !isSarBullishP; + isSarSwitchedToBearish = + isSarBearish && + !isSarBearishP; + + // + // XSB ... + + // + isSBBullish = sBarCloseBuffer[pIndex] > sBarOpenBuffer[pIndex]; + isSBBullishP = sBarCloseBuffer[p2Index] > sBarOpenBuffer[p2Index]; + + // + isSBBearish = sBarCloseBuffer[pIndex] < sBarOpenBuffer[pIndex]; + isSBBearishP = sBarCloseBuffer[p2Index] < sBarOpenBuffer[p2Index]; + + // + isSBSwitchedToBullish = + isSBBullish && + !isSBBullishP; + isSBSwitchedToBearish = + isSBBearish && + !isSBBearishP; + + // + mSBMin = MathMin(sBarCloseBuffer[pIndex], sBarOpenBuffer[pIndex]); + mSBMax = MathMax(sBarCloseBuffer[pIndex], sBarOpenBuffer[pIndex]); + + // + mSBPMin = MathMin(sBarCloseBuffer[p2Index], sBarOpenBuffer[p2Index]); + mSBPMax = MathMax(sBarCloseBuffer[p2Index], sBarOpenBuffer[p2Index]); + + // + // XHKS ... + + // + isHKSBullish = hkSBarCloseBuffer[pIndex] > hkSBarOpenBuffer[pIndex]; + isHKSBullishP = hkSBarCloseBuffer[p2Index] > hkSBarOpenBuffer[p2Index]; + + // + isHKSBearish = hkSBarCloseBuffer[pIndex] < hkSBarOpenBuffer[pIndex]; + isHKSBearishP = hkSBarCloseBuffer[p2Index] < hkSBarOpenBuffer[p2Index]; + + // + isHKSSwitchedToBullish = + isHKSBullish && + !isHKSBullishP; + isHKSSwitchedToBearish = + isHKSBearish && + !isHKSBearishP; + + // + mHKSMin = MathMin(hkSBarCloseBuffer[pIndex], hkSBarOpenBuffer[pIndex]); + mHKSMax = MathMax(hkSBarCloseBuffer[pIndex], hkSBarOpenBuffer[pIndex]); + + // + mHKSPMin = MathMin(hkSBarCloseBuffer[p2Index], hkSBarOpenBuffer[p2Index]); + mHKSPMax = MathMax(hkSBarCloseBuffer[p2Index], hkSBarOpenBuffer[p2Index]); + + // + // XKI ... + + // + isKIBullish = kiStateBuffer[pIndex] > 0; + isKIBullishP = kiStateBuffer[p2Index] > 0; + + // + isKIBearish = kiStateBuffer[pIndex] < 0; + isKIBearishP = kiStateBuffer[p2Index] < 0; + + // + isSameKI = kiBuffer[pIndex] == kiBuffer[p2Index]; + isSameBullishKI = + isSameKI && + isKIBullish; + isSameBearishKI = + isSameKI && + isKIBearish; + + // + isKISwitchedToBullish = + isKIBullish && + !isKIBullishP; + isKISwitchedToBearish = + isKIBearish && + !isKIBearishP; + + // + // XTREND ... + + // + isTrendBullish = trendStateBuffer[pIndex] > 0; + isTrendBullishP = trendStateBuffer[p2Index] > 0; + + // + isTrendBearish = trendStateBuffer[pIndex] < 0; + isTrendBearishP = trendStateBuffer[p2Index] < 0; + + // + isTrendSwitchedToBullish = + isTrendBullish && + !isTrendBullishP; + isTrendSwitchedToBearish = + isTrendBearish && + !isTrendBearishP; + + // + // Detecting Counters and Direction Shifts and it's related Conditions ... + + // + // XPV Counters ... + + // + if (isSamePeak) + { + // + mSamePeakCount++; + mSamePeakGoldenMin = + mSamePeakGoldenMin == 0 + ? peakGoldenBuffer[pIndex] + : MathMin(mSamePeakGoldenMin, peakGoldenBuffer[pIndex]); + mSamePeakGoldenMax = + mSamePeakGoldenMax == 0 + ? peakGoldenBuffer[pIndex] + : MathMax(mSamePeakGoldenMax, peakGoldenBuffer[pIndex]); + } + + // + if (isSameVale) + { + // + mSameValeCount++; + mSameValeGoldenMin = + mSameValeGoldenMin == 0 + ? valeGoldenBuffer[pIndex] + : MathMin(mSameValeGoldenMin, valeGoldenBuffer[pIndex]); + mSameValeGoldenMax = + mSameValeGoldenMax == 0 + ? valeGoldenBuffer[pIndex] + : MathMax(mSameValeGoldenMax, valeGoldenBuffer[pIndex]); + } + + // + if (isSamePeakGolden) + { + mSamePeakGoldenCount++; + } + + // + if (isSameValeGolden) + { + mSameValeGoldenCount++; + } + + // + // XSB Shifts ... + + // + // Detection ... + if (isSBSwitchedToBullish || + isSBSwitchedToBearish) + { + // + mDirShift.at = iPBar.time; + mDirShift.symbol = _Symbol; + mDirShift.period = _Period; + + // + mDirShift.type = "XSBSHFT"; + + // + mDirShift.after = 0; + mDirShift.before = 0; + + // + if (isSBSwitchedToBullish) + { + // + mDirShift.after = mSBMax; + mDirShift.before = mSBPMax; + mDirShift.shiftTo = X_DIRECTION_BULLISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBullishSBChanges // + ); + } + } + + // + if (isSBSwitchedToBearish) + { + // + mDirShift.after = mSBMin; + mDirShift.before = mSBPMin; + mDirShift.shiftTo = X_DIRECTION_BEARISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBearishSBChanges // + ); + } + } + + // + mDirShift.Clean(); + } + + // + // Parsers ... + + // + mHas = isSBBullish && + HasChild(mBearishSBChanges); + if (mHas) + { + isBullishSBBreakedLast = mSBMin > mBearishSBChanges[ArraySize(mBearishSBChanges) - 1].after; + } + + // + mHas = isSBBearish && + HasChild(mBullishSBChanges); + if (mHas) + { + isBearishSBBreakedLast = mSBMax < mBullishSBChanges[ArraySize(mBullishSBChanges) - 1].after; + } + + // + // Counters ... + + // + if (!isSBSwitchedToBullish && + !isSBSwitchedToBearish) + { + // + bool isDBullish = + isSBBullish && + isSBBullishP; + if (isDBullish) + { + mSameBullishSBCount++; + } + + // + bool isDBearish = + isSBBearish && + isSBBearishP; + if (isDBearish) + { + mSameBearishSBCount++; + } + + // + if (isDBullish || + isDBearish) + { + mSameSBCount++; + } + } + + // + // XSAR Shifts ... + + // + // Detection ... + if (isSarSwitchedToBullish || + isSarSwitchedToBearish) + { + // + mDirShift.at = iPBar.time; + mDirShift.symbol = _Symbol; + mDirShift.period = _Period; + + // + mDirShift.type = "XSARSHFT"; + + // + mDirShift.after = sarBuffer[pIndex]; + mDirShift.before = sarBuffer[p2Index]; + + // + if (isSarSwitchedToBullish) + { + // + mDirShift.shiftTo = X_DIRECTION_BULLISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBullishSarChanges // + ); + } + } + + // + if (isSarSwitchedToBearish) + { + // + mDirShift.shiftTo = X_DIRECTION_BEARISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBearishSarChanges // + ); + } + } + + // + mDirShift.Clean(); + } + + // + // Parsers ... + + // + mHas = isSarBullish && + HasChild(mBearishSarChanges); + if (mHas) + { + isBullishSarBreakedLast = sarBuffer[pIndex] > mBearishSarChanges[ArraySize(mBearishSarChanges) - 1].after; + } + + // + mHas = isSarBearish && + HasChild(mBullishSarChanges); + if (mHas) + { + isBearishSarBreakedLast = sarBuffer[pIndex] < mBullishSarChanges[ArraySize(mBullishSarChanges) - 1].after; + } + + // + // Counters ... + + // + if (!isSarSwitchedToBullish && + !isSarSwitchedToBearish) + { + // + bool isDBullish = + isSarBullish && + isSarBullishP; + if (isDBullish) + { + mSameBullishSarCount++; + } + + // + bool isDBearish = + isSarBearish && + isSarBearishP; + if (isDBearish) + { + mSameBearishSarCount++; + } + + // + if (isDBullish || + isDBearish) + { + mSameSarCount++; + } + } + + // + // XHKS Shifts ... + + // + // Detection ... + if (isHKSSwitchedToBullish || + isHKSSwitchedToBearish) + { + // + mDirShift.at = iPBar.time; + mDirShift.symbol = _Symbol; + mDirShift.period = _Period; + + // + mDirShift.type = "XHKSSHFT"; + + // + mDirShift.after = 0; + mDirShift.before = 0; + + // + if (isHKSSwitchedToBullish) + { + // + mDirShift.after = mHKSMax; + mDirShift.before = mHKSPMax; + mDirShift.shiftTo = X_DIRECTION_BULLISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBullishHKSChanges // + ); + } + } + + // + if (isHKSSwitchedToBearish) + { + // + mDirShift.after = mHKSMin; + mDirShift.before = mHKSPMin; + mDirShift.shiftTo = X_DIRECTION_BEARISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBearishHKSChanges // + ); + } + } + + // + mDirShift.Clean(); + } + + // + // Parsers ... + + // + mHas = isHKSBullish && + HasChild(mBearishHKSChanges); + if (mHas) + { + isBullishHKSBreakedLast = mHKSMin > mBearishHKSChanges[ArraySize(mBearishHKSChanges) - 1].after; + } + + // + mHas = isHKSBearish && + HasChild(mBullishHKSChanges); + if (mHas) + { + isBearishHKSBreakedLast = mHKSMax < mBullishHKSChanges[ArraySize(mBullishHKSChanges) - 1].after; + } + + // + // Counters ... + + // + if (!isHKSSwitchedToBullish && + !isHKSSwitchedToBearish) + { + // + bool isDBullish = + isHKSBullish && + isHKSBullishP; + if (isDBullish) + { + mSameBullishHKSCount++; + } + + // + bool isDBearish = + isHKSBearish && + isHKSBearishP; + if (isDBearish) + { + mSameBearishHKSCount++; + } + + // + if (isDBullish || + isDBearish) + { + mSameHKSCount++; + } + } + + // + // XKI Shifts ... + + // + // Detection ... + if (isKISwitchedToBullish || + isKISwitchedToBearish) + { + // + mDirShift.at = iPBar.time; + mDirShift.symbol = _Symbol; + mDirShift.period = _Period; + + // + mDirShift.type = "XKISHFT"; + + // + mDirShift.after = kiBuffer[pIndex]; + mDirShift.before = kiBuffer[p2Index]; + + // + if (isKISwitchedToBullish) + { + // + mDirShift.shiftTo = X_DIRECTION_BULLISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBullishKIChanges // + ); + } + } + + // + if (isKISwitchedToBearish) + { + // + mDirShift.shiftTo = X_DIRECTION_BEARISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBearishKIChanges // + ); + } + } + + // + mDirShift.Clean(); + } + + // + // Parsers ... + + // + mHas = isKIBullish && + HasChild(mBearishKIChanges); + if (mHas) + { + isBullishKIBreakedLast = kiBuffer[pIndex] > mBearishKIChanges[ArraySize(mBearishKIChanges) - 1].after; + } + + // + mHas = isKIBearish && + HasChild(mBullishKIChanges); + if (mHas) + { + isBearishKIBreakedLast = kiBuffer[pIndex] < mBullishKIChanges[ArraySize(mBullishKIChanges) - 1].after; + } + + // + // Counters ... + + // + if (isSameKI) + { + mSameKICount++; + } + + // + if (isSameBullishKI) + { + mSameBullishKICount++; + } + + // + if (isSameBearishKI) + { + mSameBearishKICount++; + } + + // + // XTREND Shifts ... + + // + // Detection ... + if (isTrendSwitchedToBullish || + isTrendSwitchedToBearish) + { + // + mDirShift.at = iPBar.time; + mDirShift.symbol = _Symbol; + mDirShift.period = _Period; + + // + mDirShift.type = "XTRENDSHFT"; + + // + mDirShift.after = trendBuffer[pIndex]; + mDirShift.before = trendBuffer[p2Index]; + + // + if (isTrendSwitchedToBullish) + { + // + mDirShift.shiftTo = X_DIRECTION_BULLISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBullishTrendChanges // + ); + } + } + + // + if (isTrendSwitchedToBearish) + { + // + mDirShift.shiftTo = X_DIRECTION_BEARISH; + + // + if (mDirShift.IsValid()) + { + // + AddIfNotExists( + mDirShift, + mBearishTrendChanges // + ); + } + } + + // + mDirShift.Clean(); + } + + // + // Parsers ... + + // + mHas = isTrendBullish && + HasChild(mBearishTrendChanges); + if (mHas) + { + isBullishTrendBreakedLast = trendBuffer[pIndex] > mBearishTrendChanges[ArraySize(mBearishTrendChanges) - 1].after; + } + + // + mHas = isTrendBearish && + HasChild(mBullishTrendChanges); + if (mHas) + { + isBearishTrendBreakedLast = trendBuffer[pIndex] < mBullishTrendChanges[ArraySize(mBullishTrendChanges) - 1].after; + } + + // + // Counters ... + + // + if (!isTrendSwitchedToBullish && + !isTrendSwitchedToBearish) + { + // + bool isDBullish = + isTrendBullish && + isTrendBullishP; + if (isDBullish) + { + mSameBullishTrendCount++; + } + + // + bool isDBearish = + isTrendBearish && + isTrendBearishP; + if (isDBearish) + { + mSameBearishTrendCount++; + } + + // + if (isDBullish || + isDBearish) + { + mSameTrendCount++; + } + } + + // + // + // + + // + // Cleanup Resources ... + + // + iBar.Clean(); + iPBar.Clean(); + mDirShift.Clean(); +} + +/** + * Detect POI(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DetectPOIs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Some Requirements ... + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Recieve Bar ... + XOHCL iBar; + XOHCL iPBar; + mHas = iBar.Init( + _Symbol, + _Period, + barIndex + // + ); + mHas = + mHas && + iBar.GetPreviousBar(iPBar); + if (!mHas) + { + return; + } + + // + // Liquidities ... + if (mDetectLiquidities) + { + // + if (isLiquidity) + { + // + XBoxZone iLiq; + + // + iLiq.type = "XLIQ"; + iLiq.symbol = _Symbol; + iLiq.period = _Period; + + // + if (isBullishLiquidity) + { + // + iLiq.at = iBar.time; + iLiq.lower = iBar.low; + iLiq.to = iBar.NextAt(); + iLiq.from = iBar.BeforeOn(); + iLiq.upper = iBar.GetDown(); + iLiq.dir = X_DIRECTION_BULLISH; + + // + if (iLiq.IsValid()) + { + // + AddIfNotExists( + iLiq, + mBullishLiquidities // + ); + } + } + + // + if (isBearishLiquidity) + { + // + iLiq.at = iBar.time; + iLiq.upper = iBar.high; + iLiq.to = iBar.NextAt(); + iLiq.lower = iBar.GetUp(); + iLiq.from = iBar.BeforeOn(); + iLiq.dir = X_DIRECTION_BEARISH; + + // + if (iLiq.IsValid()) + { + // + AddIfNotExists( + iLiq, + mBearishLiquidities // + ); + } + } + + // + iLiq.Clean(); + } + } + + // + // Range Breakes ... + int mRangeBreakesMinLength = 5; + if (mDetectRangeBreakes) + { + // + XBoxZone iRB; + + // + iRB.type = "XRNGB"; + iRB.at = iPBar.time; + iRB.to = iPBar.time; + iRB.symbol = _Symbol; + iRB.period = _Period; + + // + // Bullish ... + bool isBullishPeakPOI = + (isSamePeakOverLast && + mSamePeakCount >= mRangeBreakesMinLength); + bool isBullishValePOI = + (isSameValeOverLast && + mSameValeCount >= mRangeBreakesMinLength); + mHas = + isBullishPeakPOI || + isBullishValePOI; + if (mHas) + { + // + if (isBullishPeakPOI) + { + // + iRB.lower = mSamePeakGoldenMax; + iRB.upper = peakBuffer[barIndex + 1]; + + // + iRB.from = iPBar.time - (mSamePeakCount * PeriodSeconds(_Period)); + } + + // + if (isBullishValePOI) + { + // + iRB.upper = mSameValeGoldenMin; + iRB.lower = valeBuffer[barIndex + 1]; + + // + iRB.from = iPBar.time - (mSameValeCount * PeriodSeconds(_Period)); + } + + // + iRB.dir = X_DIRECTION_BULLISH; + + // + if (iRB.IsValid()) + { + // + AddIfNotExists( + iRB, + mBullishRangeBreakes // + ); + } + } + + // + // Bearish ... + bool isBearishPeakPOI = + (isSamePeakUnderLast && + mSamePeakCount >= mRangeBreakesMinLength); + bool isBearishValePOI = + (isSameValeUnderLast && + mSameValeCount >= mRangeBreakesMinLength); + mHas = + isBearishPeakPOI || + isBearishValePOI; + if (mHas) + { + // + if (isBearishPeakPOI) + { + // + iRB.lower = mSamePeakGoldenMax; + iRB.upper = peakBuffer[barIndex + 1]; + + // + iRB.from = iPBar.time - (mSamePeakCount * PeriodSeconds(_Period)); + } + + // + if (isBearishValePOI) + { + // + iRB.upper = mSameValeGoldenMin; + iRB.lower = valeBuffer[barIndex + 1]; + + // + iRB.from = iPBar.time - (mSameValeCount * PeriodSeconds(_Period)); + } + + // + iRB.dir = X_DIRECTION_BEARISH; + + // + if (iRB.IsValid()) + { + // + AddIfNotExists( + iRB, + mBearishRangeBreakes // + ); + } + } + + // + iRB.Clean(); + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + iPBar.Clean(); +} + +/** + * Validate Detected POI(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void ValidatePOIs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLength = 3; + + // + // Liquidities ... + + // + // Bullish ... + mHas = HasChild(mBullishLiquidities); + if (mHas) + { + // + ValidateBoxes( + mBullishLiquidities, + barIndex, + barsLength // + ); + } + + // + // Bearish ... + mHas = HasChild(mBearishLiquidities); + if (mHas) + { + // + ValidateBoxes( + mBearishLiquidities, + barIndex, + barsLength // + ); + } + + // + // Range Breakes ... + + // + // Bullish ... + mHas = HasChild(mBullishRangeBreakes); + if (mHas) + { + // + ValidateBoxes( + mBullishRangeBreakes, + barIndex, + barsLength // + ); + } + + // + // Bearish ... + mHas = HasChild(mBearishRangeBreakes); + if (mHas) + { + // + ValidateBoxes( + mBearishRangeBreakes, + barIndex, + barsLength // + ); + } + + // +} + +/** + * Draw Detected POI(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DrawPOIs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + datetime to = GetBarTime( + _Symbol, + _Period, + barIndex // + ); + + // + // Liquidities ... + if (mDrawLiquidities) + { + // + // Bullish ... + mCount = ArraySize(mBullishLiquidities); + mHas = IsValidSize(mCount); + if (mHas) + { + // + for (int i = 0; i < mCount; i++) + { + // + XBoxZone iBox = mBullishLiquidities[i]; + iBox.to = to; + + // + XCBoxObject *iBObj; + mHas = mDrawer.DrawBox( + iBox, + iBObj // + ); + if (mHas) + { + // + if (iBox.IsBullish()) + { + // + mDrawer.ApplyStyle( + iBObj, + mBullishLiquidityStyle // + ); + } + else + { + // + mDrawer.ApplyStyle( + iBObj, + mBearishLiquidityStyle // + ); + } + + // + mObjects.Add(iBObj); + } + + // + iBox.Clean(); + } + } + + // + // Bearish ... + mCount = ArraySize(mBearishLiquidities); + mHas = IsValidSize(mCount); + if (mHas) + { + // + for (int i = 0; i < mCount; i++) + { + // + XBoxZone iBox = mBearishLiquidities[i]; + iBox.to = to; + + // + XCBoxObject *iBObj; + mHas = mDrawer.DrawBox( + iBox, + iBObj // + ); + if (mHas) + { + // + if (iBox.IsBullish()) + { + // + mDrawer.ApplyStyle( + iBObj, + mBullishLiquidityStyle // + ); + } + else + { + // + mDrawer.ApplyStyle( + iBObj, + mBearishLiquidityStyle // + ); + } + + // + mObjects.Add(iBObj); + } + + // + iBox.Clean(); + } + } + } + + // + // Range Breakes ... + if (mDrawRangeBreakes) + { + // + // Bullish ... + mCount = ArraySize(mBullishRangeBreakes); + mHas = IsValidSize(mCount); + if (mHas) + { + // + for (int i = 0; i < mCount; i++) + { + // + XBoxZone iBox = mBullishRangeBreakes[i]; + iBox.to = to; + + // + XCBoxObject *iBObj; + mHas = mDrawer.DrawBox( + iBox, + iBObj // + ); + if (mHas) + { + // + if (iBox.IsBullish()) + { + // + mDrawer.ApplyStyle( + iBObj, + mBullishRangeBreakStyle // + ); + } + else + { + // + mDrawer.ApplyStyle( + iBObj, + mBearishRangeBreakStyle // + ); + } + + // + mObjects.Add(iBObj); + } + + // + iBox.Clean(); + } + } + + // + // Bearish ... + mCount = ArraySize(mBearishRangeBreakes); + mHas = IsValidSize(mCount); + if (mHas) + { + // + for (int i = 0; i < mCount; i++) + { + // + XBoxZone iBox = mBearishRangeBreakes[i]; + iBox.to = to; + + // + XCBoxObject *iBObj; + mHas = mDrawer.DrawBox( + iBox, + iBObj // + ); + if (mHas) + { + // + if (iBox.IsBullish()) + { + // + mDrawer.ApplyStyle( + iBObj, + mBullishRangeBreakStyle // + ); + } + else + { + // + mDrawer.ApplyStyle( + iBObj, + mBearishRangeBreakStyle // + ); + } + + // + mObjects.Add(iBObj); + } + + // + iBox.Clean(); + } + } + } +} + +/** + * Process Custom Analysing Senarios ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DoProcess( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Here we Can Detect Conditions ... + + // + // Check Some Requirements ... + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Recieve Bar ... + XOHCL iBar; + XOHCL iPBar; + mHas = iBar.Init( + _Symbol, + _Period, + barIndex + // + ); + mHas = + mHas && + iBar.GetPreviousBar(iPBar); + if (!mHas) + { + return; + } + + // + // Trigger Bar's Conditions ... + + // + // Bullish ... + bool isTBBullish = + // + iBar.IsBullish() && + isTriggerBarBullish && + iBar.low > iPBar.low + // + ; + + // + // Bearish ... + bool isTBBearish = + // + iBar.IsBearish() && + isTriggerBarBearish && + iBar.high < iPBar.high + // + ; + + // + // KI Breakes Validation Conditions ... + + // + // Bullish ... + bool isKIBullishBreakes = + // + isKIBullish && + iBar.IsBullish() && + iPBar.IsBreaked( + kiBuffer[barIndex + 1], + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_500, // Fibo Level ... + X_BOUNDARY_PRICE_HIGH_LOW // Boundary Type ... + ) + // + ; + + // + // Bearish ... + bool isKIBearishBreakes = + // + isKIBearish && + iBar.IsBearish() && + iPBar.IsBreaked( + kiBuffer[barIndex + 1], + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_500, // Fibo Level ... + X_BOUNDARY_PRICE_HIGH_LOW // Boundary Type ... + ) + // + ; + + // + // Conditions By ... + // - Rejecting Trend Line; + // - Trend Line is Over HK; + // - SAR Directional; + // - KI Directional; + // - HKS Directional; + + // + bool isTrendsBasedBullish = + // + isKIBullish && + isSarBullish && + isHKSBullish && + // + // TODO: Implement Trend Line is Over HKS MAX ... + // + // Rejectiong Trend Line ... + iPBar.IsBullish() && + iPBar.low < trendBuffer[barIndex + 1] && + iPBar.GetDown() > trendBuffer[barIndex + 1] + // + ; + + // + bool isTrendBasedBearish = + // + isKIBearish && + isSarBearish && + isHKSBearish && + // + // TODO: Implement Trend Line is Under HKS MIN ... + // + // Rejecting Trend Line ... + iPBar.IsBearish() && + iPBar.high > trendBuffer[barIndex + 1] && + iPBar.GetUp() < trendBuffer[barIndex + 1] + // + ; + + // + // Summarization Conditions ... + + // + // Bullish ... + mIsBullish = + // + // false + // isTBBullish && + // isKIBullishBreakes + isTrendsBasedBullish + // + ; + + // + // Bearish ... + mIsBearish = + // + // false + // isTBBearish && + // isKIBearishBreakes + isTrendBasedBearish + // + ; + + // + // Signal Summarize ... + mHasSignal = + mIsBullish || + mIsBearish; + + // + // Handling Signal ... + if (mHasSignal) + { + // + // Creating Signal Box ... + mSignalBox.type = "XSGB"; + mSignalBox.at = iBar.time; + mSignalBox.to = iBar.time; + mSignalBox.symbol = _Symbol; + mSignalBox.period = _Period; + mSignalBox.lower = iPBar.low; + mSignalBox.from = iPBar.time; + mSignalBox.upper = iPBar.high; + mSignalBox.dir = + mIsBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Converting Box to Signal ... + double rrs[] = { + 1, + 1.5, + 2, + 3 // + }; + mHas = ToSignal( + mSignalBox, + mSignal, + rrs, // Risk To Reward Ratios ... + 0 // Additional SL ... + ); + + // + // Draw Signal Box ... + if (mDrawSignalBoxes) + { + // + mHas = mSignalBox.IsValid(); + if (mHas) + { + // + XCBoxObject *iSignalBoxObj; + mHas = mDrawer.DrawBox( + mSignalBox, + iSignalBoxObj, + !mDrawSignalBoxAtLines // + ); + + // + if (mHas) + { + // + // Styling Object ... + if (mSignalBox.IsBullish()) + { + // + mDrawer.ApplyStyle( + iSignalBoxObj, + mBullishSignalBoxStyle // + ); + } + else + { + // + mDrawer.ApplyStyle( + iSignalBoxObj, + mBearishSignalBoxStyle // + ); + } + + // + // Storing Object ... + mObjects.Add(iSignalBoxObj); + } + + // + ZeroMemory(iSignalBoxObj); + } + } + + // + // Draw Signal ... + if (mDrawSignals) + { + // + mHas = mSignal.IsValid(); + if (mHas) + { + // + XCSignalObject *iSignalObj; + mHas = mDrawer.DrawSignal( + mSignal, + iSignalObj, + 3 // + ); + + // + if (mHas) + { + mObjects.Add(iSignalObj); + } + + // + ZeroMemory(iSignalObj); + } + } + + // + // Draw Arrows ... + if (mDrawSignalArrows) + { + // + int arrowWidth = 3; + int arrowCode = + mIsBullish + ? _bullishArrowCode + : _bearishArrowCode; + ENUM_X_PRICE arrowPriceType = + mIsBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + color arrowColor = + mIsBullish + ? _bullishArrowColor + : _bearishArrowColor; + ENUM_ARROW_ANCHOR arrowAnchor = + mIsBullish + ? mBullishAnchor + : mBearishAnchor; + + // + XCBarArrowObject *iSignalArrowObj; + mHas = mDrawer.CreateBarArrow( + iBar, + iSignalArrowObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + mArrowNamePrefix // + ); + if (mHas) + { + mObjects.Add(iSignalArrowObj); + } + + // + ZeroMemory(iSignalArrowObj); + } + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + iPBar.Clean(); + mSignal.Clean(); + mSignalBox.Clean(); + + // + mArrowNamePrefix = NULL; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14040626/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14040626/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/14040626/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14040626/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..c267a55 --- /dev/null +++ b/BKPS/14040626/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 + ToXString(_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/14040626/Indicators/x-saherelm.x121.xma.mq5 b/BKPS/14040626/Indicators/x-saherelm.x121.xma.mq5 new file mode 100644 index 0000000..b003e33 --- /dev/null +++ b/BKPS/14040626/Indicators/x-saherelm.x121.xma.mq5 @@ -0,0 +1,2279 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XMA +// Description: Integrates All Requirements inside +// this indicator for analyse Markets ... +// +// +// 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 XMA Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XMA" + +// +// Imports ... +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Cycles"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +input group "Calculation"; +input ENUM_SERIESMODE upperMode = MODE_HIGH; // Cycles Rnage Upper Method +input ENUM_SERIESMODE lowerMode = MODE_LOW; // Cycles Rnage Lower Method +input ENUM_MA_METHOD maMethod = MODE_SMA; // Cycles MA Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Cycles MA Applied To +input int maLength = 20; // Cycles MA Length + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showShortCycle = false; // Show Short Cycle Range +input bool showMediumCycle = false; // Show Medium Cycle Range +input bool showLongCycle = false; // Show Long Cycle Range +input bool showHindCycle = false; // Show Hind Cycle Range +input bool showShortCycleMa = false; // Show Short Cycle Ma +input bool showMediumCycleMa = false; // Show Medium Cycle Ma +input bool showLongCycleMa = false; // Show Long Cycle Ma +input bool showHindCycleMa = false; // Show Hind Cycle Ma + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +// Non Inputs ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 20 +#property indicator_plots 12 + +// +// Plot Buffers ... + +// +// SC ... + +// +#define scMaBufferIndex 0 +#define scMaBufferPlotIndex 0 +double scMaBuffer[]; + +// +#define scMaColorBufferIndex 1 +double scMaColorBuffer[]; + +// +#property indicator_label1 "SCMA" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style1 STYLE_DASHDOTDOT +#property indicator_width1 2 + +// +// MC ... + +// +#define mcMaBufferIndex 2 +#define mcMaBufferPlotIndex 1 +double mcMaBuffer[]; + +// +#define mcMaColorBufferIndex 3 +double mcMaColorBuffer[]; + +// +#property indicator_label2 "MCMA" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_DASHDOTDOT +#property indicator_width2 2 + +// +// LC ... + +// +#define lcMaBufferIndex 4 +#define lcMaBufferPlotIndex 2 +double lcMaBuffer[]; + +// +#define lcMaColorBufferIndex 5 +double lcMaColorBuffer[]; + +// +#property indicator_label3 "LCMA" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style3 STYLE_DASHDOTDOT +#property indicator_width3 2 + +// +// HC ... + +// +#define hcMaBufferIndex 6 +#define hcMaBufferPlotIndex 3 +double hcMaBuffer[]; + +// +#define hcMaColorBufferIndex 7 +double hcMaColorBuffer[]; + +// +#property indicator_label4 "HCMA" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style4 STYLE_DASHDOTDOT +#property indicator_width4 2 + +// +// CYCLES Range ... + +// +// SHORT ... + +// +#define sHHBufferIndex 8 +#define sHHBufferPlotIndex 4 +double sHHBuffer[]; + +// +#property indicator_label5 "SH" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrGray +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +#define sLLBufferIndex 9 +#define sLLBufferPlotIndex 5 +double sLLBuffer[]; + +// +#property indicator_label6 "SL" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrGray +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 10 +#define mHHBufferPlotIndex 6 +double mHHBuffer[]; + +// +#property indicator_label7 "MH" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrIndigo +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +#define mLLBufferIndex 11 +#define mLLBufferPlotIndex 7 +double mLLBuffer[]; + +// +#property indicator_label8 "ML" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrIndigo +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// LONG ... + +// +#define lHHBufferIndex 12 +#define lHHBufferPlotIndex 8 +double lHHBuffer[]; + +// +#property indicator_label9 "LH" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrGoldenrod +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 + +// +#define lLLBufferIndex 13 +#define lLLBufferPlotIndex 9 +double lLLBuffer[]; + +// +#property indicator_label10 "LL" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrGoldenrod +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +// +// HIND ... + +// +#define hHHBufferIndex 14 +#define hHHBufferPlotIndex 10 +double hHHBuffer[]; + +// +#property indicator_label11 "HH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrBrown +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define hLLBufferIndex 15 +#define hLLBufferPlotIndex 11 +double hLLBuffer[]; + +// +#property indicator_label12 "HL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrBrown +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 15 + +// +#define scMaStateBufferIndex mLastBufferIndex + 1 +double scMaStateBuffer[]; + +// +#define mcMaStateBufferIndex mLastBufferIndex + 2 +double mcMaStateBuffer[]; + +// +#define lcMaStateBufferIndex mLastBufferIndex + 3 +double lcMaStateBuffer[]; + +// +#define hcMaStateBufferIndex mLastBufferIndex + 4 +double hcMaStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// XMarketCycle sc; +int mSCLength = 0; +int mSCMALength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +int mMCMALength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +int mLCMALength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +int mHCMALength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Handlers ... +int scMaHandler = INVALID_HANDLE; +int mcMaHandler = INVALID_HANDLE; +int lcMaHandler = INVALID_HANDLE; +int hcMaHandler = INVALID_HANDLE; + +// +// Requirements ... +CArrayObj mObjects; +XCPOIDrawer *mDrawer; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + ReadBarStyle(); + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; + + // +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + ShowBars(); + + // + delete mDrawer; + ZeroMemory(mDrawer); + + // + mObjects.Clear(); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(scMaHandler); + IndicatorRelease(mcMaHandler); + IndicatorRelease(lcMaHandler); + IndicatorRelease(hcMaHandler); +} + +/** + * 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 ... + + // + int scCalculatedBars = BarsCalculated(scMaHandler); + int mcCalculatedBars = BarsCalculated(mcMaHandler); + int lcCalculatedBars = BarsCalculated(lcMaHandler); + int hcCalculatedBars = BarsCalculated(hcMaHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SC ... + scCalculatedBars >= maxLength && + // + // MC ... + mcCalculatedBars >= maxLength && + // + // LC ... + lcCalculatedBars >= maxLength && + // + // HC ... + hcCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + int copiedSCs = CopyBuffer(scMaHandler, MAIN_LINE, 0, limit, scMaBuffer); + int copiedMCs = CopyBuffer(mcMaHandler, MAIN_LINE, 0, limit, mcMaBuffer); + int copiedLCs = CopyBuffer(lcMaHandler, MAIN_LINE, 0, limit, lcMaBuffer); + int copiedHCs = CopyBuffer(hcMaHandler, MAIN_LINE, 0, limit, hcMaBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // SC ... + copiedSCs >= limit && + // + // MC ... + copiedMCs >= limit && + // + // LC ... + copiedLCs >= limit && + // + // HC ... + copiedHCs >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + result = MathMax(result, mSCMALength); + result = MathMax(result, mMCMALength); + result = MathMax(result, mLCMALength); + result = MathMax(result, mHCMALength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SC ... + + // + ArraySetAsSeries(scMaBuffer, true); + SetIndexBuffer(scMaBufferIndex, scMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scMaBufferPlotIndex, PLOT_SHOW_DATA, showShortCycleMa); + PlotIndexSetDouble(scMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(scMaColorBuffer, true); + SetIndexBuffer(scMaColorBufferIndex, scMaColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(scMaStateBuffer, true); + SetIndexBuffer(scMaStateBufferIndex, scMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // SC ... + + // + ArraySetAsSeries(mcMaBuffer, true); + SetIndexBuffer(mcMaBufferIndex, mcMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcMaBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycleMa); + PlotIndexSetDouble(mcMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(mcMaColorBuffer, true); + SetIndexBuffer(mcMaColorBufferIndex, mcMaColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(scMaStateBuffer, true); + SetIndexBuffer(mcMaStateBufferIndex, mcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // LC ... + + // + ArraySetAsSeries(lcMaBuffer, true); + SetIndexBuffer(lcMaBufferIndex, lcMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcMaBufferPlotIndex, PLOT_SHOW_DATA, showLongCycleMa); + PlotIndexSetDouble(lcMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(lcMaColorBuffer, true); + SetIndexBuffer(lcMaColorBufferIndex, lcMaColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(lcMaStateBuffer, true); + SetIndexBuffer(lcMaStateBufferIndex, lcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // HC ... + + // + ArraySetAsSeries(hcMaBuffer, true); + SetIndexBuffer(hcMaBufferIndex, hcMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcMaBufferPlotIndex, PLOT_SHOW_DATA, showHindCycleMa); + PlotIndexSetDouble(hcMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(hcMaColorBuffer, true); + SetIndexBuffer(hcMaColorBufferIndex, hcMaColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(hcMaStateBuffer, true); + SetIndexBuffer(hcMaStateBufferIndex, hcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // CYCLES ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + // SC ... + ArraySetAsSeries(scMaStateBuffer, true); + SetIndexBuffer(scMaStateBufferIndex, scMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // MC ... + ArraySetAsSeries(mcMaStateBuffer, true); + SetIndexBuffer(mcMaStateBufferIndex, mcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // LC ... + ArraySetAsSeries(lcMaStateBuffer, true); + SetIndexBuffer(lcMaStateBufferIndex, lcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // HC ... + ArraySetAsSeries(hcMaStateBuffer, true); + SetIndexBuffer(hcMaStateBufferIndex, hcMaStateBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + // Selecte Applied Cycle ... + if (result) + { + // + int normalizedMALength = maLength > 0 + ? maLength + : 1; + + // + mSCMALength = + mSCLength * normalizedMALength; + mMCMALength = + mMCLength * normalizedMALength; + mLCMALength = + mLCLength * normalizedMALength; + mHCMALength = + mHCLength * normalizedMALength; + } + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // SC ... + scMaHandler = iMA( + _Symbol, + _Period, + mSCMALength, + 0, + maMethod, + maAppliedTo // + ); + result = scMaHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MC ... + mcMaHandler = iMA( + _Symbol, + _Period, + mMCMALength, + 0, + maMethod, + maAppliedTo // + ); + result = mcMaHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // LC ... + lcMaHandler = iMA( + _Symbol, + _Period, + mLCMALength, + 0, + maMethod, + maAppliedTo // + ); + result = lcMaHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // HC ... + hcMaHandler = iMA( + _Symbol, + _Period, + mHCMALength, + 0, + maMethod, + maAppliedTo // + ); + result = hcMaHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + mDrawer = new XCPOIDrawer(); + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + scMaColorBuffer[barIndex] = hideColorIDX; + mcMaColorBuffer[barIndex] = hideColorIDX; + lcMaColorBuffer[barIndex] = hideColorIDX; + hcMaColorBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Cycle Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Cycle MAs ... + CalculateCycleMAs( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Do Process if Required ... + DoProcess( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycleRange( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycleRange( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycleRange( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycleRange( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +// +void CalculateCycleMAs( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycleMA( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + showShortCycleMa, + scMaBuffer, + scMaColorBuffer, + scMaStateBuffer // + ); + + // + // MEDIUM ... + CalculateCycleMA( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + showMediumCycleMa, + mcMaBuffer, + mcMaColorBuffer, + mcMaStateBuffer // + ); + + // + // LONG ... + CalculateCycleMA( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + showLongCycleMa, + lcMaBuffer, + lcMaColorBuffer, + lcMaStateBuffer // + ); + + // + // HIND ... + CalculateCycleMA( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + showHindCycleMa, + hcMaBuffer, + hcMaColorBuffer, + hcMaStateBuffer // + ); +} + +/** + * Calculate Specified Market Cycle Range ... + * + * @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 CalculateCycleRange( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +/** + * Calculate Specified Market Cycle MA ... + * + * @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 CalculateCycleMA( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + bool show, + double &maBuffer[], + double &colorBuffer[], + double &stateBuffer[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iOpen = open[barIndex]; + double iClose = close[barIndex]; + double iValue = maBuffer[barIndex]; + + // + bool basedOnClose = false; + + // + double iState = neuturalState; + double iColor = neuturalColorIDX; + if (basedOnClose) + { + // + iColor = + iClose > iValue + ? bullishColorIDX + : iClose < iValue + ? bearishColorIDX + : neuturalColorIDX; + + // + iState = + iClose > iValue + ? bullishState + : iClose < iValue + ? bearishState + : neuturalState; + } + else + { + // + iColor = + iLow > iValue + ? bullishColorIDX + : iHigh < iValue + ? bearishColorIDX + : neuturalColorIDX; + + // + iState = + iLow > iValue + ? bullishState + : iHigh < iValue + ? bearishState + : neuturalState; + } + stateBuffer[barIndex] = iState; + colorBuffer[barIndex] = show + ? iColor + : hideColorIDX; +} + +// +// Process Bars ... +void DoProcess( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + if (isFirstBar) + { + return; + } + + // + int minRequiredRange = 20; + if (barIndex > maxBarIndex - 1) + { + return; + } + + // + XOHCL iBar; + bool has = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + + // + return; + } + + // + // Reading Values ... + + // + // Bars Info ... + + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iOpen = open[barIndex]; + double iClose = close[barIndex]; + + // + double iPLow = low[barIndex + 1]; + double iPHigh = high[barIndex + 1]; + double iPOpen = open[barIndex + 1]; + double iPClose = close[barIndex + 1]; + + // + // SC ... + + // + double iSCLL = sLLBuffer[barIndex]; + double iSCHH = sHHBuffer[barIndex]; + + // + double iPSCLL = sLLBuffer[barIndex + 1]; + double iPSCHH = sHHBuffer[barIndex + 1]; + + // + double iSCMa = scMaBuffer[barIndex]; + double iPSCMa = scMaBuffer[barIndex + 1]; + + // + double iSCMaState = scMaStateBuffer[barIndex]; + double iPSCMaState = scMaStateBuffer[barIndex + 1]; + + // + // + // + + // + bool isSCMaBullish = + iSCMaState > 0; + bool isPSCMaBullish = + iPSCMaState > 0; + + // + bool isSCMaBearish = + iSCMaState < 0; + bool isPSCMaBearish = + iPSCMaState < 0; + + // + bool isSCMaSwitchedToBullish = + isSCMaBullish && + !isPSCMaBullish; + + // + bool isSCMaSwitchedToBearish = + isSCMaBearish && + !isPSCMaBearish; + + // + // MC ... + + // + double iMCLL = mLLBuffer[barIndex]; + double iMCHH = mHHBuffer[barIndex]; + + // + double iPMCLL = mLLBuffer[barIndex + 1]; + double iPMCHH = mHHBuffer[barIndex + 1]; + + // + double iMCMa = mcMaBuffer[barIndex]; + double iPMCMa = mcMaBuffer[barIndex + 1]; + + // + double iMCMaState = mcMaStateBuffer[barIndex]; + double iPMCMaState = mcMaStateBuffer[barIndex + 1]; + + // + // + // + + // + bool isMCMaBullish = + iMCMaState > 0; + bool isPMCMaBullish = + iPMCMaState > 0; + + // + bool isMCMaBearish = + iMCMaState < 0; + bool isPMCMaBearish = + iPMCMaState < 0; + + // + bool isMCMaSwitchedToBullish = + isMCMaBullish && + !isPMCMaBullish; + + // + bool isMCMaSwitchedToBearish = + isMCMaBearish && + !isPMCMaBearish; + + // + // + // + + // + bool isSCMaOverMC = + iSCMa > iMCMa; + bool isPSCMaOverMC = + iPSCMa > iPMCMa; + + // + bool isSCMaUnderMC = + iSCMa < iMCMa; + bool isPSCMaUnderMC = + iPSCMa < iPMCMa; + + // + bool isSCMaCrossedOverMC = + isSCMaOverMC && + !isPSCMaOverMC; + + // + bool isSCMaCrossedUnderMC = + isSCMaUnderMC && + !isPSCMaUnderMC; + + // + // + // + + // + bool isSCLLOverMCLL = + iSCLL > iMCLL; + bool isPSCLLOverMCLL = + iPSCLL > iPMCLL; + + // + bool isSCLLUnderMCLL = + iSCLL < iMCLL; + bool isPSCLLUnderMCLL = + iPSCLL < iPMCLL; + + // + bool isSCHHOverMCHH = + iSCHH > iMCHH; + bool isPSCHHOverMCHH = + iPSCHH > iPMCHH; + + // + bool isSCHHUnderMCHH = + iSCHH < iMCHH; + bool isPSCHHUnderMCHH = + iPSCHH < iPMCHH; + + // + bool isSCLLCrossedOverMCLL = + isSCLLOverMCLL && + !isPSCLLOverMCLL; + + // + bool isSCLLCrossedUnderMCLL = + isSCLLUnderMCLL && + !isPSCLLUnderMCLL; + + // + bool isSCHHCrossedOverMCHH = + isSCHHOverMCHH && + !isPSCHHOverMCHH; + + // + bool isSCHHCrossedUnderMCHH = + isSCHHUnderMCHH && + !isPSCHHUnderMCHH; + + // + // LC ... + + // + double iLCLL = lLLBuffer[barIndex]; + double iLCHH = lHHBuffer[barIndex]; + + // + double iPLCLL = lLLBuffer[barIndex + 1]; + double iPLCHH = lHHBuffer[barIndex + 1]; + + // + double iLCMa = lcMaBuffer[barIndex]; + double iPLCMa = lcMaBuffer[barIndex + 1]; + + // + double iLCMaState = lcMaStateBuffer[barIndex]; + double iPLCMaState = lcMaStateBuffer[barIndex + 1]; + + // + // + // + + // + bool isLCMaBullish = + iLCMaState > 0; + bool isPLCMaBullish = + iPLCMaState > 0; + + // + bool isLCMaBearish = + iLCMaState < 0; + bool isPLCMaBearish = + iPLCMaState < 0; + + // + bool isLCMaSwitchedToBullish = + isLCMaBullish && + !isPLCMaBullish; + + // + bool isLCMaSwitchedToBearish = + isLCMaBearish && + !isPLCMaBearish; + + // + // + // + + // + bool isMCMaOverLC = + iMCMa > iLCMa; + bool isPMCMaOverLC = + iPMCMa > iPLCMa; + + // + bool isMCMaUnderLC = + iMCMa < iLCMa; + bool isPMCMaUnderLC = + iPMCMa < iPLCMa; + + // + bool isMCMaCrossedOverLC = + isMCMaOverLC && + !isPMCMaOverLC; + + // + bool isMCMaCrossedUnderLC = + isMCMaUnderLC && + !isPMCMaUnderLC; + + // + // + // + + // + bool isMCLLOverLCLL = + iMCLL > iLCLL; + bool isPMCLLOverLCLL = + iPMCLL > iPLCLL; + + // + bool isMCLLUnderLCLL = + iMCLL < iLCLL; + bool isPMCLLUnderLCLL = + iPMCLL < iPLCLL; + + // + bool isMCHHOverLCHH = + iMCHH > iLCHH; + bool isPMCHHOverLCHH = + iPMCHH > iPLCHH; + + // + bool isMCHHUnderLCHH = + iMCHH < iLCHH; + bool isPMCHHUnderLCHH = + iPMCHH < iPLCHH; + + // + bool isMCLLCrossedOverLCLL = + isMCLLOverLCLL && + !isPMCLLOverLCLL; + + // + bool isMCLLCrossedUnderLCLL = + isMCLLUnderLCLL && + !isPMCLLUnderLCLL; + + // + bool isMCHHCrossedOverLCHH = + isMCHHOverLCHH && + !isPMCHHOverLCHH; + + // + bool isMCHHCrossedUnderLCHH = + isMCHHUnderLCHH && + !isPMCHHUnderLCHH; + + // + // HC ... + + // + double iHCLL = hLLBuffer[barIndex]; + double iHCHH = hHHBuffer[barIndex]; + + // + double iPHCLL = hLLBuffer[barIndex + 1]; + double iPHCHH = hHHBuffer[barIndex + 1]; + + // + double iHCMa = hcMaBuffer[barIndex]; + double iPHCMa = hcMaBuffer[barIndex + 1]; + + // + double iHCMaState = hcMaStateBuffer[barIndex]; + double iPHCMaState = hcMaStateBuffer[barIndex + 1]; + + // + // + // + + // + bool isHCMaBullish = + iHCMaState > 0; + bool isPHCMaBullish = + iPHCMaState > 0; + + // + bool isHCMaBearish = + iHCMaState < 0; + bool isPHCMaBearish = + iPHCMaState < 0; + + // + bool isHCMaSwitchedToBullish = + isHCMaBullish && + !isPHCMaBullish; + + // + bool isHCMaSwitchedToBearish = + isHCMaBearish && + !isPHCMaBearish; + + // + // + // + + // + bool isLCMaOverHC = + iLCMa > iHCMa; + bool isPLCMaOverHC = + iPLCMa > iPHCMa; + + // + bool isLCMaUnderHC = + iLCMa < iHCMa; + bool isPLCMaUnderHC = + iPLCMa < iPHCMa; + + // + bool isLCMaCrossedOverHC = + isLCMaOverHC && + !isPLCMaOverHC; + + // + bool isLCMaCrossedUnderHC = + isLCMaUnderHC && + !isPLCMaUnderHC; + + // + // + // + + // + bool isLCLLOverHCLL = + iLCLL > iHCLL; + bool isPLCLLOverHCLL = + iPLCLL > iPHCLL; + + // + bool isLCLLUnderHCLL = + iLCLL < iHCLL; + bool isPLCLLUnderHCLL = + iPLCLL < iPHCLL; + + // + bool isLCHHOverHCHH = + iLCHH > iHCHH; + bool isPLCHHOverHCHH = + iPLCHH > iPHCHH; + + // + bool isLCHHUnderHCHH = + iLCHH < iHCHH; + bool isPLCHHUnderHCHH = + iPLCHH < iPHCHH; + + // + bool isLCLLCrossedOverHCLL = + isLCLLOverHCLL && + !isPLCLLOverHCLL; + + // + bool isLCLLCrossedUnderHCLL = + isLCLLUnderHCLL && + !isPLCLLUnderHCLL; + + // + bool isLCHHCrossedOverHCHH = + isLCHHOverHCHH && + !isPLCHHOverHCHH; + + // + bool isLCHHCrossedUnderHCHH = + isLCHHUnderHCHH && + !isPLCHHUnderHCHH; + + // + // Check Price Inside Cloud Zone ... + + // + double iCloudZoneUpper = MathMax(iLCMa, iHCMa); + double iCloudZoneLower = MathMin(iLCMa, iHCMa); + + // + bool isICloudZoneUpperBullish = + iCloudZoneUpper == iLCMa + ? isLCMaBullish + : isHCMaBullish; + bool isICloudZoneLowerBullish = + iCloudZoneLower == iLCMa + ? isLCMaBullish + : isHCMaBullish; + + // + bool isICloudZoneUpperBearish = + iCloudZoneUpper == iLCMa + ? isLCMaBearish + : isHCMaBearish; + bool isICloudZoneLowerBearish = + iCloudZoneLower == iLCMa + ? isLCMaBearish + : isHCMaBearish; + + // + double iPCloudZoneUpper = MathMax(iPLCMa, iPHCMa); + double iPCloudZoneLower = MathMin(iPLCMa, iPHCMa); + + // + bool isIPCloudZoneUpperBullish = + iPCloudZoneUpper == iPLCMa + ? isPLCMaBullish + : isPHCMaBullish; + bool isIPCloudZoneLowerBullish = + iPCloudZoneLower == iPLCMa + ? isPLCMaBullish + : isPHCMaBullish; + + // + bool isIPCloudZoneUpperBearish = + iPCloudZoneUpper == iPLCMa + ? isPLCMaBearish + : isPHCMaBearish; + bool isIPCloudZoneLowerBearish = + iPCloudZoneLower == iPLCMa + ? isPLCMaBearish + : isPHCMaBearish; + + // + double iPressureZoneUpper = MathMax(iSCMa, iMCMa); + double iPressureZoneLower = MathMin(iSCMa, iMCMa); + + // + bool isIPressureZoneUpperBullish = + iPressureZoneUpper == iSCMa + ? isSCMaBullish + : isMCMaBullish; + bool isIPressureZoneLowerBullish = + iPressureZoneLower == iSCMa + ? isSCMaBullish + : isMCMaBullish; + + // + bool isIPressureZoneUpperBearish = + iPressureZoneUpper == iSCMa + ? isSCMaBearish + : isMCMaBearish; + bool isIPressureZoneLowerBearish = + iPressureZoneLower == iSCMa + ? isSCMaBearish + : isMCMaBearish; + + // + double iPPressureZoneUpper = MathMax(iPSCMa, iPMCMa); + double iPPressureZoneLower = MathMin(iPSCMa, iPMCMa); + + // + bool isIPPressureZoneUpperBullish = + iPPressureZoneUpper == iPSCMa + ? isPSCMaBullish + : isPMCMaBullish; + bool isIPPressureZoneLowerBullish = + iPPressureZoneLower == iPSCMa + ? isPSCMaBullish + : isPMCMaBullish; + + // + bool isIPPressureZoneUpperBearish = + iPPressureZoneUpper == iPSCMa + ? isPSCMaBearish + : isPMCMaBearish; + bool isIPPressureZoneLowerBearish = + iPPressureZoneLower == iPSCMa + ? isPSCMaBearish + : isPMCMaBearish; + + // + // + // + + // + bool isBullishPriceInsideCloudZone = + iLow < iCloudZoneUpper && + iLow > iCloudZoneLower; + + // + bool isPBullishPriceInsideCloudZone = + iPLow < iPCloudZoneUpper && + iPLow > iPCloudZoneLower; + + // + bool isBearishPriceInsideCloudZone = + iHigh > iCloudZoneLower && + iHigh < iCloudZoneUpper; + + // + bool isPBearishPriceInsideCloudZone = + iPHigh > iPCloudZoneLower && + iPHigh < iPCloudZoneUpper; + + // + bool isPriceBullishCrossedInsideCloudZone = + isBullishPriceInsideCloudZone && + !isPBullishPriceInsideCloudZone; + + // + bool isPriceBearishCrossedInsideCloudZone = + isBearishPriceInsideCloudZone && + !isPBearishPriceInsideCloudZone; + + // + bool hasBullishPressure = + iLow > iPressureZoneUpper; + + // + bool hasBearishPressure = + iHigh < iPressureZoneLower; + + // + // Detect Cloud Direction ... + + // + bool isBullish = + hasBullishPressure && + isBullishPriceInsideCloudZone; + + // + bool isBearish = + hasBearishPressure && + isBearishPriceInsideCloudZone; + + // + has = isBullish || + isBearish; + + // + // Draw Inside Zone Arrow ... + if (has) + { + // + int arrowWidth = 3; + int arrowCode = 159; + ENUM_ARROW_ANCHOR arrowAnchor = + isBullish + ? ANCHOR_BOTTOM + : ANCHOR_TOP; + color arrowColor = + isBullish + ? mDrawer.defaultBullishStyle.clr + : mDrawer.defaultBearishStyle.clr; + ENUM_X_PRICE arrowPriceType = + isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *iObj; + has = mDrawer.CreateBarArrow( + iBar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor // + ); + if (has) + { + mObjects.Add(iObj); + } + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Indicators/x-saherelm.xom1.mq5 b/BKPS/14040626/Indicators/x-saherelm.xom1.mq5 new file mode 100644 index 0000000..36589db --- /dev/null +++ b/BKPS/14040626/Indicators/x-saherelm.xom1.mq5 @@ -0,0 +1,1397 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XOM1 +// Description: Integrates All Requirements inside +// this indicator for analyse Markets Based on OM1 ... +// +// +// 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 XOM1 Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "XOM1" + +// +// Imports ... +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Calculation"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// PV ... +input ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +input ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method + +// +// Others ... +input ENUM_X_FIBO_LEVELS upperZoneLevel = X_FIBO_LEVEL_618; // Upper Zone Level +input ENUM_X_FIBO_LEVELS lowerZoneLevel = X_FIBO_LEVEL_382; // Lower Zone Level +input double sarStep = 0.02; // SAR Step +input double sarMax = 0.2; // SAR Maximum +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To +input int maFastLength = 7; // Fast MA Length +input int maSlowLength = 20; // Slow MA Length + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showFiboZone = true; // Show Fibo Zone + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +input int sarArrowCode = 159; // Parabolic Sar Arrow Code +input int peakArrowCode = 159; // Peaks Arrow Code +input int valeArrowCode = 159; // Vales Arrow Code + +// +// Non Inputs ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 21 +#property indicator_plots 7 + +// +// Plot Buffers ... + +// +// Fast MA ... + +// +#define maFastBufferIndex 0 +#define maFastBufferPlotIndex 0 +double maFastBuffer[]; + +// +#define maFastColorBufferIndex 1 +double maFastColorBuffer[]; + +// +#property indicator_label1 "FastMA" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrYellow, clrOrangeRed, clrGray +#property indicator_width1 2 + +// +// Slow MA ... + +// +#define maSlowBufferIndex 2 +#define maSlowBufferPlotIndex 1 +double maSlowBuffer[]; + +// +#define maSlowColorBufferIndex 3 +double maSlowColorBuffer[]; + +// +#property indicator_label2 "SlowMA" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width2 2 + +// +// SAR ... + +// +#define sarBufferIndex 4 +#define sarBufferPlotIndex 2 +double sarBuffer[]; + +// +#define sarColorBufferIndex 5 +double sarColorBuffer[]; + +// +#property indicator_label3 "SAR" +#property indicator_type3 DRAW_COLOR_ARROW +#property indicator_color3 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width3 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 6 +#define peakBufferPlotIndex 3 +double peakBuffer[]; + +// +#property indicator_label4 "PEAK" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrMagenta +#property indicator_width4 3 + +// +// VALES ... + +// +#define valeBufferIndex 7 +#define valeBufferPlotIndex 4 +double valeBuffer[]; + +// +#property indicator_label5 "VALE" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrAqua +#property indicator_width5 3 + +// +// FIBO Upper ... + +// +#define fiboUpperBufferIndex 8 +#define fiboUpperBufferPlotIndex 5 +double fiboUpperBuffer[]; + +// +#property indicator_label6 "FIBUP" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrAqua +#property indicator_width6 2 + +// +// FIBO Lower ... + +// +#define fiboLowerBufferIndex 9 +#define fiboLowerBufferPlotIndex 6 +double fiboLowerBuffer[]; + +// +#property indicator_label7 "FIBLO" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrMagenta +#property indicator_width7 2 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 9 + +// +// MA ... + +// +#define maFastStateBufferIndex mLastBufferIndex + 1 +double maFastStateBuffer[]; + +// +#define maSlowStateBufferIndex mLastBufferIndex + 2 +double maSlowStateBuffer[]; + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 3 +double sarStateBuffer[]; + +// +// CYCLES ... + +// +// SC ... + +// +#define sHHBufferIndex mLastBufferIndex + 4 +double sHHBuffer[]; + +// +#define sLLBufferIndex mLastBufferIndex + 5 +double sLLBuffer[]; + +// +// MC ... + +// +#define mHHBufferIndex mLastBufferIndex + 6 +double mHHBuffer[]; + +// +#define mLLBufferIndex mLastBufferIndex + 7 +double mLLBuffer[]; + +// +// LC ... + +// +#define lHHBufferIndex mLastBufferIndex + 8 +double lHHBuffer[]; + +// +#define lLLBufferIndex mLastBufferIndex + 9 +double lLLBuffer[]; + +// +// HC ... + +// +#define hHHBufferIndex mLastBufferIndex + 10 +double hHHBuffer[]; + +// +#define hLLBufferIndex mLastBufferIndex + 11 +double hLLBuffer[]; + +// +// Variables, Properties and etc ... + +// +// 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; + +// +int sarHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Requirements ... +CArrayObj mObjects; +XCPOIDrawer *mDrawer; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + // 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 + + // + delete mDrawer; + ZeroMemory(mDrawer); + + // + mObjects.Clear(); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(sarHandler); + IndicatorRelease(maFastHandler); + 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 ... + + // + // MA ... + int maFastCalculatedBars = BarsCalculated(maFastHandler); + int maSlowCalculatedBars = BarsCalculated(maSlowHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + // + // 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 ... + + // + // MA ... + int copiedMAFasts = CopyBuffer(maFastHandler, MAIN_LINE, 0, limit, maFastBuffer); + int copiedMASlows = CopyBuffer(maSlowHandler, MAIN_LINE, 0, limit, maSlowBuffer); + + // + // SAR ... + int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + // + // SAR ... + copiedSARs >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + result = MathMax(result, maFastLength); + result = MathMax(result, maSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Fast MA ... + + // + ArraySetAsSeries(maFastBuffer, true); + SetIndexBuffer(maFastBufferIndex, maFastBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maFastBufferPlotIndex, PLOT_SHOW_DATA, showMAFast); + PlotIndexSetDouble(maFastBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(maFastColorBuffer, true); + SetIndexBuffer(maFastColorBufferIndex, maFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(maFastStateBuffer, true); + SetIndexBuffer(maFastStateBufferIndex, maFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow MA ... + + // + ArraySetAsSeries(maSlowBuffer, true); + SetIndexBuffer(maSlowBufferIndex, maSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maSlowBufferPlotIndex, PLOT_SHOW_DATA, showMASlow); + PlotIndexSetDouble(maSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(maSlowColorBuffer, true); + SetIndexBuffer(maSlowColorBufferIndex, maSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(maSlowStateBuffer, true); + SetIndexBuffer(maSlowStateBufferIndex, maSlowStateBuffer, INDICATOR_CALCULATIONS); + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSAR); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // FIBO Zone ... + + // + ENUM_DRAW_TYPE fiboZoneDrawType = showFiboZone ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(fiboUpperBuffer, true); + SetIndexBuffer(fiboUpperBufferIndex, fiboUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboUpperBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboUpperBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Lower ... + ArraySetAsSeries(fiboLowerBuffer, true); + SetIndexBuffer(fiboLowerBufferIndex, fiboLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLowerBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboLowerBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + // CYCLES ... + + // + // SC ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + // MC ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + // LC ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + // HC ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // Fast MA ... + maFastHandler = iMA( + _Symbol, + _Period, + maFastLength, + 0, + maMethod, + maAppliedTo // + ); + result = maFastHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Slow MA ... + maSlowHandler = iMA( + _Symbol, + _Period, + maSlowLength, + 0, + maMethod, + maAppliedTo // + ); + result = maSlowHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + mDrawer = new XCPOIDrawer(); + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Calculate Bars Limit and First Bar Index ... + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // TODO: Fill Buffers as Empty ... +} + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Common Requirements ... + + // + // CYCLES Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Fast MA ... + double iFastMa = maFastBuffer[barIndex]; + double maFastState = close[barIndex] > iFastMa + ? bullishState + : close[barIndex] < iFastMa + ? bearishState + : neuturalState; + double maFastColor = close[barIndex] > iFastMa + ? bullishColorIDX + : close[barIndex] < iFastMa + ? bearishColorIDX + : neuturalColorIDX; + maFastStateBuffer[barIndex] = maFastState; + maFastColorBuffer[barIndex] = showMAFast + ? maFastColor + : hideColorIDX; + + // + // Slow MA ... + double iSlowMa = maSlowBuffer[barIndex]; + double maSlowState = close[barIndex] > iSlowMa + ? bullishState + : close[barIndex] < iSlowMa + ? bearishState + : neuturalState; + double maSlowColor = close[barIndex] > iSlowMa + ? bullishColorIDX + : close[barIndex] < iSlowMa + ? bearishColorIDX + : neuturalColorIDX; + maSlowStateBuffer[barIndex] = maSlowState; + maSlowColorBuffer[barIndex] = showMASlow + ? maSlowColor + : hideColorIDX; + + // + // SAR ... + double iSar = sarBuffer[barIndex]; + double sarState = low[barIndex] > iSar + ? bullishState + : high[barIndex] < iSar + ? bearishState + : neuturalState; + double sarColor = low[barIndex] > iSar + ? bullishColorIDX + : high[barIndex] < iSar + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = sarState; + sarColorBuffer[barIndex] = showSAR + ? sarColor + : hideColorIDX; + + // + // FIBO Zone ... + + // + double iPeak = peakBuffer[barIndex]; + double iVale = valeBuffer[barIndex]; + + // + double iFiboUp = GetFibonacciLevel( + iPeak, + iVale, + upperZoneLevel, + X_DIRECTION_BULLISH); + + // + double iFiboLo = GetFibonacciLevel( + iPeak, + iVale, + lowerZoneLevel, + X_DIRECTION_BULLISH); + + // + fiboUpperBuffer[barIndex] = iFiboUp; + fiboLowerBuffer[barIndex] = iFiboLo; +} + +// +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Libraries/x-saherelm.common.extensions.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.common.extensions.lib.mq5 new file mode 100644 index 0000000..1a4429b --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -0,0 +1,6994 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonExtensionsLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Classes/x-saherelm.x-md5.class.mq5" +#include "../Libraries/x-saherelm.x-enums.lib.mq5" + +// +#include + +// +// Constants ... +#define X_MIN_SIZE 0 +#define X_INVALID_INDEX -1 + +// +// START Value Checkers ... +// + +// +// Check a Value Not Empty ... +template +bool NotEmpty(T value) +{ + return value != EMPTY_VALUE; +} + +// +// Check a Value Not Empty and Zero ... +template +bool NotEmptyZero(T value) +{ + return value != 0 && + value != EMPTY_VALUE; +} + +// +// END Value Checkers ... +// + +// +// START Validators ... +// + +/** + * Validate Strings ... + * + * @param value: string + * + * @return ( bool ) + */ +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} +bool IsSpecifiedValid(string value) +{ + return IsValid(value); +} + +/** + * Validate Date ... + * + * @param value: datetime + * + * @return ( bool ) + */ +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} +bool IsSpecifiedValid(datetime value) +{ + return IsValid(value); +} + +/** + * Validate Time Frame ... + * + * @param value: ENUM_TIMEFRAMES member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} + +/** + * Validate Specific Period Mode ... + * + * @param mMethod: ENUM_X_PERIOD_METHOD member, Period Select Method ... + * @param mPeriod: ENUM_TIMEFRAMES member, Selected Period ... + * + * @return ( bool ) + */ +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NONE + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} +bool IsSpecifiedValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + return IsValid( + mMethod, + mPeriod // + ); +} + +/** + * Validate a Size Value ... + * + * @param value: int, Provided Size ... + * + * @return ( bool ) + */ +bool IsValidSize(int value) +{ + // + bool result = value > X_MIN_SIZE; + + // + return result; +} + +/** + * Check a Given Index is Valid or not ... + * + * @param value: int, Provided Index ... + * + * @return ( bool ) + */ +bool IsValidIndex(int value) +{ + return value >= X_MIN_SIZE; +} + +// +// END Validators ... +// + +// +// START Normalizations ... +// + +/** + * Normalize Symbol ... + * + * @param value: string, Provided Symbols ... + * + * @return ( string ) + */ +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +/** + * Normalize Time ... + * + * @param value: datetime, Provided Time ... + * + * @return ( datetime ) + */ +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +/** + * Normalize Period ... + * + * @param value: ENUM_TIMEFRAMES member, Provided Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +/** + * Normalize Market Cycle ... + * + * @param value: ENUM_X_MARKET_CYCLES, Provided Cycle ... + * + * @return ( ENUM_X_MARKET_CYCLES ) + */ +ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value) +{ + // + ENUM_X_MARKET_CYCLES result = value; + + // + if (!IsValid(result)) + { + result = X_MARKET_CYCLE_SHORT; + } + + // + return value; +} + +/** + * Normalize Price Boundary ... + * + * @param value: ENUM_X_BOUNDARY_PRICE, Provided Boundary Mode ... + * + * @return ( ENUM_X_BOUNDARY_PRICE ) + */ +ENUM_X_BOUNDARY_PRICE NormalizeBoundary(ENUM_X_BOUNDARY_PRICE value) +{ + // + ENUM_X_BOUNDARY_PRICE result = value; + + // + if (!IsValid(result)) + { + result = X_BOUNDARY_PRICE_HIGH_LOW; + } + + // + return result; +} + +/** + * Normalize Integer Value ... + * + * @param value: int, Provided Value ... + * @param min: int, Minimum Allowed Value ... + * @param max: int, Maximum Allowed Value ... + * + * @return ( int ) + */ +int NormalizeInt( + int value, + int min = 0, + int max = INT_MAX // +) +{ + // + if (value < min) + { + value = min; + } + + // + if (value > max) + { + value = max; + } + + // + return value; +} + +/** + * Normalize Double Value ... + * + * @param value: double, Provided Value ... + * @param min: double, Minimum Allowed Value ... + * @param max: double, Maximum Allowed Value ... + * + * @return ( double ) + */ +double NormalizeDouble( + double value, + double min = 0, + double max = DBL_MAX // +) +{ + // + if (value < min) + { + value = min; + } + + // + if (value > max) + { + value = max; + } + + // + return value; +} + +/** + * Normalize Index based on Collection ... + * + * @param index: int, Provided Index ... + * @param buffer: Collection Reference ... + */ +template +bool NormalizeIndex( + int &index, + T &buffer[] // +) +{ + // + bool result = false; + + // + int size = ArraySize(buffer); + result = IsValidSize(size); + if (!result) + { + return result; + } + + // + if (!IsValidIndex(index)) + { + index = X_MIN_SIZE; + } + + // + if (index > size - 1) + { + index = size - 1; + } + + // + result = IsValidIndex(index) && + index >= X_MIN_SIZE && + index < size; + + // + return result; +} + +/** + * Normalize Start and Count based on Specified Buffer ... + * + * @param start: int, Provided Start index ... + * @param count: int, Provided Number of Iteration ... + * @param buffer: Collection instance ... + */ +template +void NormalizeCount( + int &start, + int &count, + T &buffer[] // +) +{ + // + // Validate Buffer Size ... + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return; + } + + // + // Normalization Start ... + NormalizeIndex( + start, + buffer // + ); + + // + if (count < start) + { + count = (start - count); + } + + // + // Normalization Count ... + + // + if (count < 0) + { + count = start; + } + + // + if (count > bufferSize - start) + { + count = bufferSize - start; + } +} + +/** + * Normalize a Volume ... + * + * @param mVolume: double, Provided Volume ... + * @param mSymbol: string, Specified Symbol ... + * @param mLength: int, Provided Default floating Length ... + * + * @return ( double ) + */ +double NormalizeVolume( + double mVolume, + string mSymbol = NULL, + int mLength = 2 // +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Normalize Digits ... + int digits = GetDigits(minAvailableVolume); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +/** + * Normalize a Price Value ... + * + * @param mPrice: double, Provided Price ... + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double NormalizePrice( + double mPrice, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double tickSize = 0; + result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize); + + // + int digits = GetDigits(mSymbol); + result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits); + + // + return result; +} + +/** + * Normalize Chart Id ... + * + * @param _chartId: ulong + * + * @return ( ulong ) + */ +ulong NormalizeChartId(ulong _chartId = 0) +{ + // + if (_chartId <= 0) + { + _chartId = ChartID(); + } + + // + return _chartId; +} + +// +// END Normalizations ... +// + +// +// START Position ... +// + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_POSITION_TYPE value) +{ + // + bool result = value == POSITION_TYPE_BUY; + + // + return result; +} + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_ORDER_TYPE value) +{ + // + bool result = value == ORDER_TYPE_BUY; + + // + return result; +} + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_X_DIRECTION member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_X_DIRECTION value) +{ + // + bool result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_POSITION_TYPE value) +{ + // + bool result = value == POSITION_TYPE_SELL; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_ORDER_TYPE value) +{ + // + bool result = value == ORDER_TYPE_SELL; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_X_DIRECTION member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_X_DIRECTION value) +{ + // + bool result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Converts Opposit Direction Type ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( ENUM_POSITION_TYPE ) + */ +ENUM_POSITION_TYPE Opposit(ENUM_POSITION_TYPE value) +{ + // + ENUM_POSITION_TYPE result = NULL; + + // + bool isLong = IsLong(value); + result = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + return result; +} + +/** + * Converts Opposit Direction Type ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( ENUM_ORDER_TYPE ) + */ +ENUM_ORDER_TYPE Opposit(ENUM_ORDER_TYPE value) +{ + // + ENUM_ORDER_TYPE result = NULL; + + // + bool isLong = IsLong(value); + result = isLong + ? ORDER_TYPE_SELL + : ORDER_TYPE_BUY; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_POSITION_TYPE member ... + * + * @return ( string ) + */ +string ToXString(ENUM_POSITION_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_ORDER_TYPE member ... + * + * @return ( string ) + */ +string ToXString(ENUM_ORDER_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +/** + * Get Ask Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetAsk( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +/** + * Get Bid Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetBid( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +/** + * Get Spread Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetSpread( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} +double GetXSpread( + string mSymbol = NULL // +) +{ + return GetSpread(mSymbol); +} + +/** + * Get SPecified Symbols Volume Step ... + * + * @param mSymbol: string ... + * + * @return ( double ) + */ +double GetVolumeStep( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_STEP); + + // + return result; +} + +/** + * Get Point Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +/** + * Converts Price to Point ... + * + * @param price: double, price ... + * @param mSymbol: string, Symbol ... + * + * @return ( double ) + */ +double PriceToPoint( + double mPrice, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPrice = NormalizePrice(mPrice, mSymbol); + + // + double point = GetPoints(mSymbol); + result = mPrice / point; + + // + return result; +} + +/** + * Get Digits Length ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +/** + * Get Entry Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_POSITION_TYPE member, Specified Entry type ... + * + * @return ( double ) + */ +double GetEntry( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} +double GetXEntry( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + return GetEntry(mSymbol, type); +} + +/** + * Get Entry Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_X_DIRECTION member, Specified Entry type ... + * + * @return ( double ) + */ +double GetEntry( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} +double GetXEntry( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + return GetEntry(mSymbol, type); +} + +/** + * Get Exit Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_POSITION_TYPE member, Specified Exit type ... + * + * @return ( double ) + */ +double GetExit( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} +double GetXExit( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + return GetExit(mSymbol, type); +} + +/** + * Get Exit Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_X_DIRECTION member, Specified Exit type ... + * + * @return ( double ) + */ +double GetExit( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} +double GetXExit( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + return GetExit(mSymbol, type); +} + +/** + * Retrieve Current Tick ... + */ +bool GetTick( + string mSymbol, + MqlTick &tick // +) +{ + return SymbolInfoTick(mSymbol, tick); +} + +// +// Peak and Vales ... + +int FindXSwing( + ENUM_X_SWING_TYPE mType, + string mSymbol = NULL, + ENUM_TIMEFRAMES mPeriod = NULL, + int mFromIndex = 0, + int mShoulders = 5 // +) +{ + // + int result = -1; + + // + // Validate ... + if (!IsXValid(mType)) + { + return result; + } + + // + result = mFromIndex; + int foundedIDX = FindXNextSwing( + mType, + mSymbol, + mPeriod, + result - mShoulders, + mShoulders * 2 + 1 // + ); + while (foundedIDX != result) + { + // + result = FindXNextSwing( + mType, + mSymbol, + mPeriod, + result + 1, + mShoulders // + ); + + // + foundedIDX = FindXNextSwing( + mType, + mSymbol, + mPeriod, + result - mShoulders, + mShoulders * 2 + 1 // + ); + } + + // + return result; +} + +int FindXNextSwing( + ENUM_X_SWING_TYPE mType, + string mSymbol = NULL, + ENUM_TIMEFRAMES mPeriod = NULL, + int mFromIndex = 0, + int mShoulders = 5 // +) +{ + // + int result = -1; + + // + if (mFromIndex < 0) + { + mShoulders += mFromIndex; + } + + // + // Normalize ... + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + mFromIndex = NormalizeInt(mFromIndex, 0); + mShoulders = NormalizeInt(mShoulders, 3); + + // + // Validate .... + if (!IsXValid(mType)) + { + return result; + } + + // + // Converts Swing Type to Series Mode ... + ENUM_SERIESMODE mode = ToSeriesMode(mType); + result = + mode == MODE_HIGH + ? iHighest( + mSymbol, + mPeriod, + mode, + mShoulders, + mFromIndex // + ) + : iLowest( + mSymbol, + mPeriod, + mode, + mShoulders, + mFromIndex // + ); + + // + return result; +} + +// +// END Position ... +// + +// +// START Tools ... +// + +/** + * Check Expert Running in Testing Mode or not ... + * + * @return ( bool ) + */ +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQLInfoInteger(MQL_TESTER); + + // + return result; +} + +/** + * Check Expert Running in Visual Testing Mode ... + * + * @return ( bool ) + */ +bool IsRunningeOnTestVisualMode() +{ + // + bool result = false; + + // + result = IsRunningOnTestMode() && + MQLInfoInteger(MQL_VISUAL_MODE); + + // + return result; +} + +/** + * Find Chart ID ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ... + * + * @return ( long ) + */ +long FindChartID( + string mSymbol = NULL, + ENUM_TIMEFRAMES mPeriod = NULL // +) +{ + // + long result = ChartFirst(); + long first = result; + + // + while (result > 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwn = + // + chSymbol == mSymbol && + chPeriod == mPeriod + // + ; + if (isOwn) + { + break; + } + + // + result = ChartNext(result); + } + + // + return result; +} + +/** + * Retrieve Available Symbols ... + * + * @param symbols: string Collection reference to Hold Symbols ... + * @param onlyInWatchList: bool, Force Extracts only Watch List Symbols ... + * + * @return ( int ) + */ +int GetAllSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false // Specified Retrieve only Symbols which in Watch List +) +{ + // + int result = 0; + + // + Clean(symbols); + + // + int count = SymbolsTotal(onlyInWatchList); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + string iSymbol = SymbolName( + i, + onlyInWatchList // + ); + if (!IsValid(iSymbol)) + { + continue; + } + + // + Add( + iSymbol, + symbols // + ); + } + + // + result = ArraySize(symbols); + + // + return result; +} + +/** + * Filter Symbols Collections ... + * + * @param query: string, Provided Query to Search Symbols ... + * @param symbols: string, Collection resources to Hold's Filtered results ... + * @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ... + * @param ignoreCase: bool, Ignore Case Sesitive ... + * @param querySeparator: string, Provided Separator of Query ... + * + * @return ( int ) + */ +int FilterSymbols( + string query, + string &symbols[], + bool onlyInWatchList = false, + bool ignoreCase = true, + string querySeparator = "," // If Provided means query is a Collection of Queries and need to be Splitted +) +{ + // + int result = 0; + + // + Clean(symbols); + + // + if (!IsValid(query)) + { + return result; + } + + // + // Check Query is an String array or not ... + string mQueries[]; + int queriesCount = 0; + if (IsValid(querySeparator) && Contains(querySeparator, query, true)) + { + // + queriesCount = SplitContent( + mQueries, + query, + querySeparator // + ); + } + + // + string allSymbols[]; + int allSymbolsCount = GetAllSymbols( + allSymbols, + onlyInWatchList // + ); + if (allSymbolsCount <= 0) + { + return result; + } + + // + // Loop Through all Symbols ... + for (int i = 0; i < allSymbolsCount; i++) + { + // + string iSymbol = allSymbols[i]; + + // + bool isFilterPassed = false; + if (queriesCount == 0) + { + // + isFilterPassed = Contains( + query, + iSymbol, + ignoreCase // + ); + } + else if (queriesCount > 0) + { + // + isFilterPassed = Contains( + mQueries, + iSymbol, + ignoreCase // + ); + } + + // + if (isFilterPassed) + { + // + Add( + iSymbol, + symbols // + ); + } + } + + // + result = ArraySize(symbols); + + // + return result; +} + +/** + * Extract Symbols to Find Only USD Side Assets ... + * + * @param symbols: string, Collection resources to Hold's Filtered results ... + * @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ... + * @param ignoreCase: bool, Ignore Case Sesitive ... + * @param querySeparator: string, Provided Separator of Query ... + * + * @return ( int ) + */ +int FilterUSDSymbols( + string &symbols[], + bool onlyInWatchList = false, + bool ignoreCase = true, + string querySeparator = "," // +) +{ + // + return FilterSymbols( + "USD", + symbols, + onlyInWatchList, + ignoreCase, + querySeparator // + ); +} + +/** + * Get Digits Length of Specified Double Value ... + * + * @param value: double, Provided Value ... + * + * @return ( int ) + */ +int GetDigits(double value) +{ + // + int d = 0; + double p = 1; + while (MathRound(value * p) / p != value) + { + p = MathPow(10, ++d); + } + + // + return d; +} + +/** + * Retrieve Specific Object Types Name ... + * + * @param t: T object reference ... + * + * @return ( string ) + * + */ +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +/** + * Get Specified Types Token ... + * + * @param item: T, object reference ... + * + * @return ( string ) + */ +template +string GetToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} +template +string GetSpecificToken(T &item) +{ + return GetToken(item); +} + +/** + * Generate Unique Tags ... + * + * @param model: T, object reference ... + * + * @return ( string ) + */ +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToXString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + XSCMD5 *md5; + md5 = new XCMD5(); + + // + result = md5.Hash(tag); + + // + ZeroMemory(md5); + + // + return result; +} + +/** + * Hash Specified Content ... + * + * @param content: T, Proveded Content ... + * + * @return ( string ) + */ +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToXString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + XCMD5 *md5; + md5 = new XCMD5(); + + // + result = md5.Hash(strContent); + + // + delete md5; + ZeroMemory(md5); + + // + return result; +} + +/** + * Calculate Fibo Level ... + * + * @param mUp: double, Specified Upper Price ... + * @param mDown: double, Specified Lower Price ... + * @param mLevel: ENUM_X_FIBO_LEVELS member, Specified Fibo Level ... + * @param mForDir: ENUM_X_DIRECTION member, Specified Calculation Direction ... + * + * @return ( double ) + */ +double GetFibonacciLevel( + double mUp, + double mDown, + ENUM_X_FIBO_LEVELS mLevel, + ENUM_X_DIRECTION mForDir // +) +{ + // + double result = 0; + + // + double levelValue = GetFiboLevelValue(mLevel); + + // + bool isValid = + // + mUp > 0 && + mDown > 0 && + levelValue > 0 && + mUp > mDown && + HasDirection(mForDir) + // + ; + if (!isValid) + { + return result; + } + + // + bool isBullish = IsBullish(mForDir); + + // + double ling = mUp - mDown; + double pLevel = (ling / 100) * (levelValue * 100); + + // + result = + isBullish + ? mUp - pLevel + : mDown + pLevel; + + // + return result; +} + +/** + * Calculate Sspecified Buffer's Moving Averages ... + * + * @param rates_total: Integer, number of items ... + * @param prev_calculated: Integer, Previous Calculate Items ... + * @param begin: Integer, Bar Index ... + * @param period: Integer, Moving Average Length ... + * @param source: Double Array, Specified Array for Calculating Moving Averages ... + * @param buffer: Double Array, Specified Array to Apply Calculated Moving Average on it ... + * @param method: ENUM_MA_METHOD member Specified Moving Average Calculation Method ... + * + * @return ( int ) + */ +int iMAOnBuffer( + const int _rates_total, + const int _prev_calculated, + const int _begin, + const int _period, + const double &_source[], + double &_buffer[], + ENUM_X_MA_METHOD _method = X_MA_MODE_SMA // +) +{ + // + int result = 0; + + // + if ( + _period < 0 || + _rates_total <= 0 || + _prev_calculated < 0 || + _method == X_MA_MODE_NONE || + _prev_calculated > _rates_total) + { + return result; + } + + // + switch (_method) + { + // + case X_MA_MODE_SMA: + result = SimpleMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_EMA: + result = ExponentialMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_LWMA: + result = LinearWeightedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_SMMA: + result = SmoothedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + } + + // + return result; +} + +// +// END Tools ... +// + +// +// START String ... +// + +/** + * Search a Content Contains Specific String or not ... + * + * @param mQuery: string, Search Query ... + * @param mContent: string, Search Content ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( bool ) + */ +bool Contains( + string mQuery, + string mContent, + bool ignoreCase = true // +) +{ + // + bool result = false; + + // + // Validate Query ... + result = IsValid(mQuery); + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + // Normalize Inputs ... + string query = mQuery; + string content = mContent; + if (ignoreCase) + { + // + StringToLower(query); + StringToLower(content); + } + + // + int queryIdx = StringFind( + content, + query); + + // + result = queryIdx >= 0; + + // + return result; +} + +/** + * Search a Content Contains Specifics Query or not ... + * + * @param mQueries: string collection, Search Queries ... + * @param mContent: string, Search Content ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( bool ) + */ +bool Contains( + string &mQueries[], + string mContent, + bool ignoreCase = true // +) +{ + // + bool result = false; + + // + // Validate Queries ... + int queriesCount = ArraySize(mQueries); + result = queriesCount > 0; + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + int containsCount = 0; + for (int i = 0; i < queriesCount; i++) + { + // + bool isContains = Contains( + mQueries[i], + mContent, + ignoreCase); + + // + if (!isContains) + { + // + result = false; + break; + } + + // + containsCount++; + } + + // + result = containsCount == queriesCount; + + // + return result; +} + +/** + * Search a Content and Extract Occuranse Indexes ... + * + * @param mQuery: string, Search Query ... + * @param mContent: string, Search Content ... + * @param result: int collection reference, Holds Founded Indexes ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( int ) + */ +int FindIndexes( + string mQuery, + string mContent, + int &result[], + bool ignoreCase = false // +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Inputs ... + if (!IsValid(mQuery) || + !IsValid(mContent)) + { + return mResult; + } + + // + // Apply Ignore Case if Provided ... + if (ignoreCase) + { + // + bool isConverted = StringToLower(mQuery); + if (!isConverted) + { + return mResult; + } + + // + isConverted = StringToLower(mContent); + if (!isConverted) + { + return mResult; + } + } + + // + // Search First Index ... + int lastPos = 0; + int idx = StringFind( + mContent, + mQuery, + lastPos // + ); + while (idx >= 0) + { + // + // Add Position to Result ... + Add( + idx, + result // + ); + + // + lastPos = idx + StringLen(mQuery); + idx = StringFind( + mContent, + mQuery, + lastPos // + ); + } + + // + mResult = ArraySize(result); + + // + return mResult; +} +int FindXIndexes( + string mQuery, + string mContent, + int &result[], + bool ignoreCase = false // +) +{ + return FindXIndexes(mQuery, mContent, result, ignoreCase); +} + +/** + * Convert From String ... + * + * @param value: string, Provided Value ... + * + * @return ( T ) + */ +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +/** + * Converts to String ... + * + * @param value: T, Provided Value ... + * + * @return ( string ) + */ +template +string ToXString(T value) +{ + return (string)value; +} + +string Trim(string value) +{ + // + string result = NULL; + + // + result = value; + + // + StringTrimRight(result); + StringTrimLeft(result); + + // + return result; +} + +// +// Used In Report or Summary Generators ... +string ToXString( + string prefix, // Title + bool value, // Value + bool ignoreFalseConditions = true, // Ignore False Conditions + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + bool canSet = + IsBoolean(ToXString(value)) + ? (bool)value || !ignoreFalseConditions + : true; + + // + result = canSet + ? prefix + + prefixSeparator + " " + + ToXString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +template +string ToXString( + string prefix, // Title + T value, // Value + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = prefix + + prefixSeparator + " " + + ToXString(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 ToXString( + const T &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} + +/** + * Check a String Value is Boolean or Not ... + * + * @param value: string representation of value ... + * + * @return ( bool ) + */ +bool IsBoolean(string value) +{ + // + bool result = false; + + // + string istring = value; + string normalizedValue = ToXString(istring); + StringToLower(normalizedValue); + normalizedValue = Trim(normalizedValue); + + // + result = + !IsValid(normalizedValue) + ? false + : (normalizedValue == "true" || + normalizedValue == "false"); + + // + return result; +} + +/** + * Converts String to boolean ... + * + * @param value: string, Provided Value ... + * + * @return ( bool ) + */ +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (!IsBoolean(value) || + StringLen(value) <= 0) + { + return result; + } + + // + value = Trim(value); + StringToLower(value); + + // + bool isTrue = value == "true"; + bool isFalse = value == "false"; + + // + result = isTrue + ? true + : false; + + // + return result; +} + +// +// Split an String Representation of an Array ... +int SplitContent( + string &result[], // Hold Result ... + string content, // Source ... + string separator = ",", // Separator ... + bool forceCleanResult = true // Clean Result ... +) +{ + // + int mResult = 0; + + // + if (forceCleanResult) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + if (separator == NULL || StringLen(separator) == 0) + { + separator = ","; + } + + // + if (StringLen(content) == 0) + { + return mResult; + } + + // + StringSplit( + content, + StringGetCharacter( + separator, + 0), + result); + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Extract an Array of Contents ... +int ExtractStrings( + string &result[], // Hold Result + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Args ... + int sourceLength = StringLen(source); + int startLength = StringLen(startString); + int endLength = StringLen(endString); + + // + int minRequiredLength = startLength + endLength; + + // + if ( + endLength <= 0 || + startLength <= 0 || + sourceLength <= 0 || + sourceLength < minRequiredLength) + { + return mResult; + } + + // + // Make a Copy of Source for Manipulating ... + string workStr = source; + + // + // Define a Loop ... + while (StringLen(workStr) > minRequiredLength) + { + // + // Find Item ... + string item = ExtractString( + workStr, + startString, + endString); + + // + // Breakout when couldn't find anymore item ... + int itemLength = StringLen(item); + if (itemLength <= 0) + { + break; + } + + // + // Prepare Item Source String for Replacing in Work String ... + string itemSource = startString + item + endString; + + // + // Add Item to Result Array ... + Add( + item, + result); + + // + // Replace Item Soure in Work String ... + StringReplace( + workStr, + itemSource, + ""); + } + + // + // Calculate Size of Array ... + mResult = ArraySize(result); + + // + return mResult; +} + +// +string ExtractSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + return ExtractString( + surrounded, + mToken + startString, + endString + // + ); +} + +// +int ParseIntSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (int)strContent; + + // + return result; +} + +long ParseLongSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + long result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (long)strContent; + + // + return result; +} + +string ParseStringSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (string)strContent; + + // + return result; +} + +double ParseDoubleSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + double result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (double)strContent; + + // + return result; +} + +datetime ParseTimeSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + datetime result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (datetime)strContent; + + // + return result; +} + +// +int ParseIntArraySurrounded( + int &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + int iValue = (int)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseLongArraySurrounded( + long &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + long iValue = (long)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseDoubleArraySurrounded( + double &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + double iValue = (double)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseTimeArraySurrounded( + datetime &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + datetime iValue = (datetime)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +// +// Surround an String by Specific Token ... +template +string Surround( + string mToken, // an String which used to Tokenize + T &value, // a Value for Tokenize it + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string strValue = ToXString(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 = ToXString(value); + if (!IsValid(valueStr)) + { + return result; + } + + // + result = Surround( + mToken, + valueStr, + startString, + endString + // + ); + + // + return result; +} + +// +// END String ... +// + +// +// START Cycles ... +// + +/** + * Converts String To Period ... + * + * @param value: string ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES ToPeriod(string value) +{ + // + if (StringLen(value) == 0) + { + return _Period; + } + + // + StringTrimLeft(value); + StringTrimRight(value); + + // + ENUM_TIMEFRAMES result = _Period; + + // + if (value == "M1") + { + result = PERIOD_M1; + } + else if (value == "M2") + { + result = PERIOD_M2; + } + else if (value == "M3") + { + result = PERIOD_M3; + } + else if (value == "M4") + { + result = PERIOD_M4; + } + else if (value == "M5") + { + result = PERIOD_M5; + } + else if (value == "M6") + { + result = PERIOD_M6; + } + else if (value == "M10") + { + result = PERIOD_M10; + } + else if (value == "M12") + { + result = PERIOD_M12; + } + else if (value == "M15") + { + result = PERIOD_M15; + } + else if (value == "M20") + { + result = PERIOD_M20; + } + else if (value == "M30") + { + result = PERIOD_M30; + } + else if (value == "H1") + { + result = PERIOD_H1; + } + else if (value == "H2") + { + result = PERIOD_H2; + } + else if (value == "H3") + { + result = PERIOD_H3; + } + else if (value == "H4") + { + result = PERIOD_H4; + } + else if (value == "H6") + { + result = PERIOD_H6; + } + else if (value == "H8") + { + result = PERIOD_H8; + } + else if (value == "H12") + { + result = PERIOD_H12; + } + else if (value == "D1") + { + result = PERIOD_D1; + } + else if (value == "W1") + { + result = PERIOD_W1; + } + else if (value == "MN1") + { + result = PERIOD_MN1; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_TIMEFRAMES member ... + * + * @return ( string ) + */ +string ToXString(ENUM_TIMEFRAMES value) +{ + // + string result = ""; + + // + string mPStr = EnumToString(value); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[1]; + + // + return result; +} + +// +// Retrieve All Available Period as an Array ...s +int GetAllAvailablePeriods( + ENUM_TIMEFRAMES &result[] // Holds Result ... +) +{ + // + Clean(result); + + // + Add( + PERIOD_M1, + result + // + ); + + // + Add( + PERIOD_M2, + result + // + ); + + // + Add( + PERIOD_M3, + result + // + ); + + // + Add( + PERIOD_M4, + result + // + ); + + // + Add( + PERIOD_M5, + result + // + ); + + // + Add( + PERIOD_M6, + result + // + ); + + // + Add( + PERIOD_M10, + result + // + ); + + // + Add( + PERIOD_M12, + result + // + ); + + // + Add( + PERIOD_M15, + result + // + ); + + // + Add( + PERIOD_M20, + result + // + ); + + // + Add( + PERIOD_M30, + result + // + ); + + // + Add( + PERIOD_H1, + result + // + ); + + // + Add( + PERIOD_H2, + result + // + ); + + // + Add( + PERIOD_H3, + result + // + ); + + // + Add( + PERIOD_H4, + result + // + ); + + // + Add( + PERIOD_H6, + result + // + ); + + // + Add( + PERIOD_H8, + result + // + ); + + // + Add( + PERIOD_H12, + result + // + ); + + // + Add( + PERIOD_D1, + result + // + ); + + // + Add( + PERIOD_W1, + result + // + ); + + // + Add( + PERIOD_MN1, + result + // + ); + + // + int mResult = ArraySize(result); + + // + return mResult; +} + +// +// Get Specific Time Frame Start Candle Time ... +datetime GetPeriodStartTime( + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + datetime mTime = NULL // Specified Bar Time of Host Period ... +) +{ + // + // Normalize Arg ... + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + datetime result = GetBarTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + return result; +} + +// +// Retrieve Nearest Period base on Given Period ... +ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_M5; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_M10; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_M20; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H1; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H3; + break; + + // + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H4: + result = PERIOD_H6; + break; + + // + case PERIOD_H6: + result = PERIOD_H8; + break; + + // + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Mediest Period base on Given Period ... +ENUM_TIMEFRAMES GetMediestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_M10; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_M15; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_M30; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H4; + break; + + // + case PERIOD_H3: + result = PERIOD_H6; + break; + + // + case PERIOD_H4: + result = PERIOD_H8; + break; + + // + case PERIOD_H6: + result = PERIOD_H12; + break; + + // + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Longest Period base on Given Period ... +ENUM_TIMEFRAMES GetLongestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_M30; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_H1; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H2; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H6; + break; + + // + case PERIOD_H3: + result = PERIOD_H8; + break; + + // + case PERIOD_H4: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + result = PERIOD_D1; + break; + + // + case PERIOD_H8: + result = PERIOD_W1; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Hindmost Period base on Given Period ... +ENUM_TIMEFRAMES GetHindMostPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_H1; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_H2; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H4; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H6; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H8; + break; + + // + case PERIOD_H3: + result = PERIOD_H12; + break; + + // + case PERIOD_H4: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + result = PERIOD_W1; + break; + + // + case PERIOD_H8: + result = PERIOD_MN1; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Specified Cycles Period related to Host Period ... +ENUM_TIMEFRAMES GetCyclePeriod( + ENUM_X_MARKET_CYCLES mCycle = NULL, // Specified Cycle + ENUM_TIMEFRAMES mPeriod = NULL // Host Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + mPeriod = NormalizePeriod(mPeriod); + mCycle = NormalizeCycle(mCycle); + + // + switch (mCycle) + { + // + // Short ... + case X_MARKET_CYCLE_SHORT: + result = GetNearestPeriod(mPeriod); + break; + + // + // Medium ... + case X_MARKET_CYCLE_MEDIUM: + result = GetMediestPeriod(mPeriod); + break; + + // + // Long ... + case X_MARKET_CYCLE_LONG: + result = GetLongestPeriod(mPeriod); + break; + + // + // Hind ... + case X_MARKET_CYCLE_HIND: + result = GetHindMostPeriod(mPeriod); + break; + } + + // + return result; +} + +// +// Calculate a Cycle Length based on Host Period ... +int GetCycleLengthOn( + ENUM_TIMEFRAMES _hostPeriod, + ENUM_X_MARKET_CYCLES _cycle, + ENUM_X_PERIOD_METHOD _method, + ENUM_TIMEFRAMES _period // +) +{ + // + int result = 0; + + // + // Validate ... + bool isValid = + // + IsValid(_hostPeriod) && + IsValid(_method, _Period) + // + ; + if (!isValid) + { + return result; + } + + // + // Calculate Period ... + isValid = + _method != X_PERIOD_NONE && + _cycle != X_MARKET_CYCLE_UNKNOWN; + if (!isValid) + { + return result; + } + + // + if (_method == X_PERIOD_AUTO) + { + // + _period = GetCyclePeriod( + _cycle, + _hostPeriod // + ); + } + isValid = IsValid(_period); + if (!isValid) + { + return result; + } + + // + int _hostPeriodSeconds = PeriodSeconds(_hostPeriod); + int _periodSeconds = PeriodSeconds(_period); + + // + isValid = _periodSeconds >= _hostPeriodSeconds; + if (!isValid) + { + return result; + } + + // + result = _periodSeconds / _hostPeriodSeconds; + + // + return result; +} + +/** + * Retrieve Sharp Change Info for Specified Period ... + * + * @param priceChange: double, required Price Change ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ... + * + * @return ( int ) + */ +int GetPeriodSharpData( + double &priceChange, + ENUM_TIMEFRAMES mPeriod = NULL // +) +{ + // + int result = 0; + + // + priceChange = 0.0; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + // + priceChange = 0.000006; + result = 14; + break; + + // + case PERIOD_M2: + // + priceChange = 0.000006; + result = 14; + break; + + // + case PERIOD_M3: + // + priceChange = 0.00007; + result = 14; + break; + + // + case PERIOD_M4: + // + priceChange = 0.000007; + result = 14; + break; + + // + case PERIOD_M5: + // + priceChange = 0.000009; + result = 14; + break; + + // + case PERIOD_M6: + // + priceChange = 0.000009; + result = 14; + break; + + // + case PERIOD_M10: + // + priceChange = 0.00001; + result = 12; + break; + + // + case PERIOD_M12: + // + priceChange = 0.000011; + result = 11; + break; + + // + case PERIOD_M15: + // + priceChange = 0.000011; + result = 9; + break; + + // + case PERIOD_M20: + // + priceChange = 0.000012; + result = 9; + break; + + // + case PERIOD_M30: + // + priceChange = 0.000012; + result = 7; + break; + + // + case PERIOD_H1: + // + priceChange = 0.000013; + result = 5; + break; + + // + case PERIOD_H2: + // + priceChange = 0.000013; + result = 5; + break; + + // + case PERIOD_H3: + // + priceChange = 0.000014; + result = 5; + break; + + // + case PERIOD_H4: + // + priceChange = 0.000014; + result = 5; + break; + + // + case PERIOD_H6: + // + priceChange = 0.000015; + result = 5; + break; + + // + case PERIOD_H8: + // + priceChange = 0.000017; + result = 5; + break; + + // + case PERIOD_H12: + // + priceChange = 0.000017; + result = 5; + break; + + // + case PERIOD_D1: + // + priceChange = 0.000019; + result = 3; + break; + + // + case PERIOD_W1: + // + priceChange = 0.00002; + result = 3; + break; + + // + case PERIOD_MN1: + // + priceChange = 0.000021; + result = 3; + break; + } + + // + return result; +} + +// +// END Cycles ... +// + +// +// START Collections ... +// + +// +// Add Specified Item to Array ... +template +int Add( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} +template +int AddSpecified( + 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 SpecifiedHasChild(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[]) +{ + // + if (!HasChild(buffer)) + { + return; + } + + // + // ArrayResize(buffer, 0); + ArrayFree(buffer); + ZeroMemory(buffer); +} +template +void SpecifiedClean(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; +} +template +int FindXIndex( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + return FindIndex(item, buffer); +} + +// +// 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; +} +template +int FindXIndex( + T &item, // Item to Find + const T &items[] // Items for Search +) +{ + return FindIndex(item, items); +} + +// +// Check an Array Contains Specified Value ... +template +bool Contains( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + bool result = false; + + // + int idx = FindIndex( + item, + buffer); + result = idx > -1; + + // + return result; +} + +// +// Calculate a Buffer's Sum ... +template +double GetSum( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + return result; +} + +// +// Calculate a Buffer's Average ... +template +double GetAverage( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + // Calculate Average ... + result = result / tmpCount; + + // + return result; +} + +// +// Get Max of Specific Loopback of a Buffer ... +template +T GetMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMaxWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result < iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMaxWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMaxWidthIndex( + buffer, + index, + start, + count // + ); +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +T GetMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMinWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result > iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMinWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMinWidthIndex( + buffer, + index, + start, + count // + ); +} + +// +// Find a Value less than Specified ... +template +T FindLesserThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} +template +T FindLesserThanByIndex( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} +template +T FindBiggerThanByIndex( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find Same Values in Array ... +template +void FindSames( + T &result[], // Holds Result ... + T &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + T mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + T iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3 // +) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// END Collections ... +// + +// +// START Buffers ... +// + +// +template +bool IsSame( + T &buffer[], // Search Buffer + int count = 5, // Number of Searchs + int start = 0 // Start ... +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + result = bufferSize > 0; + if (!result) + { + return result; + } + + // + // Validate Count ... + result = start + count < bufferSize; + if (!result) + { + return result; + } + + // + T iTem = buffer[start]; + for (int i = start; i < start + count; i++) + { + // + if (iTem != buffer[i]) + { + result = false; + break; + } + + // + if (!result) + { + result = true; + } + } + + // + return result; +} + +// +// Check first Cross Over second at index ... +bool IsCrossedOver( + const double &first[], // the buffer which check crossing over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + !(first[index + 1] > second[index + 1]); + + // + return result; +} + +// +// Check first is Over second at index ... +bool IsOver( + const double &first[], // the buffer which check over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + first[index + 1] > second[index + 1]; + + // + return result; +} + +// +// Check first Cross Under second at index ... +bool IsCrossedUnder( + const double &first[], // the buffer which check crossing under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + !(first[index + 1] < second[index + 1]); + + // + return result; +} + +// +// Check first is Under second at index ... +bool IsUnder( + const double &first[], // the buffer which check under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + first[index + 1] < second[index + 1]; + + // + return result; +} + +// +// Check if a Value Increasing in Loopback ... +bool IsIncreasing( + const double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue >= fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue <= fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsTrendingUp( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = upCounts > 1 && upCounts > downCounts; + + // + return result; +} + +// +bool IsTrendingDown( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = downCounts > 1 && downCounts > upCounts; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + const double &buffer[], // Buffer + int from, // In Past Index ... + int to // In Past Index ... +) +{ + // + double result = 0; + + // + if (from > ArraySize(buffer) || to > ArraySize(buffer)) + { + return result; + } + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// END Buffers ... +// + +// +// START Time ... +// + +// +// Converts Time to Seconds ... +ulong TimeToSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = (ulong)time; + + // + return result; +} +ulong TimeToSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToSeconds(dTime); + + // + return result; +} + +// +// Converts Seconds To Time ... +datetime SecondsToTime( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime result = (datetime)seconds; + + // + return result; +} +MqlDateTime SecondsToStruct( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime dTime = SecondsToTime(seconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Time to MilliSeconds ... +ulong TimeToMilliSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = TimeToSeconds(time) * 1000; + + // + return result; +} +ulong TimeToMilliSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToMilliSeconds(dTime); + + // + return result; +} + +// +// Converts MillisSeconds to Time ... +datetime MilliSecondsToTiem( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + ulong seconds = milliSeconds / 1000; + + // + datetime result = SecondsToTime(seconds); + + // + return result; +} +MqlDateTime MilliSecondsToStruct( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + datetime dTime = MilliSecondsToTiem(milliSeconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Hours to Seconds ... +int HoursToSeconds(int value) +{ + // + int result = 0; + + // + if (value < 0) + { + value = 0; + } + + // + if (value == 0) + { + return result; + } + + // + result = value * 60 * 60; + + // + return result; +} + +// +// Retrieve DateTime Structure ... +MqlDateTime GetCurrentTime() +{ + // + MqlDateTime result = {}; + + // + datetime cTime = TimeCurrent(); + TimeToStruct(cTime, result); + + // + return result; +} + +// +// Retrieve Current Time as Seconds ... +ulong GetCurrentTimeAsSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Current Time as MilliSeconds ... +ulong GetCurrentTimeAsMilliSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +int GetLocalOffset() +{ + // + MqlDateTime cTimeStruct; + datetime cTime = TimeCurrent(cTimeStruct); + + // + MqlDateTime cLTimeStruct; + datetime cLTime = TimeLocal(cLTimeStruct); + + // + cTimeStruct.sec = 0; + cTime = StructToTime(cTimeStruct); + + // + cLTimeStruct.sec = 0; + cLTime = StructToTime(cLTimeStruct); + + // + int result = ((int)cLTime - (int)cTime); + + // + return result; +} + +// +int GetUTCRequiredTimeOffset() +{ + // + int utcOffset = TimeGMTOffset(); + int localOffset = GetLocalOffset(); + + // + int result = utcOffset + localOffset; + + // + return result; +} + +// +datetime GetUTCTime( + datetime time = NULL, + bool applyTradeServerTime = false // +) +{ + // + datetime result = NULL; + + // + NormalizeTime(time); + + // + datetime cTime = TimeCurrent(); + datetime cTimeLocal = TimeLocal(); + + // + int cLocalOffset = ((int)cTimeLocal - (int)cTime); + int gmtOffset = TimeGMTOffset(); + int offsetDelte = gmtOffset + cLocalOffset; + int requiredUTCOffset = GetUTCRequiredTimeOffset(); + if (requiredUTCOffset > 0) + { + requiredUTCOffset = -1 * requiredUTCOffset; + } + + // + int timeSeconds = (int)time; + int resultSeconds = timeSeconds + requiredUTCOffset; + + // + result = (datetime)(resultSeconds); + + // + return result; +} + +// +// Retrieve only Hour and Minute as String ... +string GetTimeString( + datetime time = NULL // +) +{ + // + NormalizeTime(time); + + // + string result = NULL; + + // + MqlDateTime tStruct; + bool isStructed = TimeToStruct(time, tStruct); + if (!isStructed) + { + return result; + } + + // + string hour = ToXString(tStruct.hour); + hour = + StringLen(hour) == 1 + ? "0" + hour + : hour; + + // + string minute = ToXString(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 = ToXString(timeStruct.year); + string month = ToXString(timeStruct.mon); + string day = ToXString(timeStruct.day); + string hour = ToXString(timeStruct.hour); + string minute = ToXString(timeStruct.min); + string second = ToXString(timeStruct.sec); + + // + result = + // + // Year ... + year + separator + + // + // Month ... + (StringLen(month) == 1 + ? "0" + month + : month) + + separator + + // + // Day ... + (StringLen(day) == 1 + ? "0" + day + : day) + + separator + + // + // Hour ... + (StringLen(hour) == 1 + ? "0" + hour + : hour) + + separator + + // + // Minute ... + (StringLen(minute) == 1 + ? "0" + minute + : minute) + + separator + + // + // Seconds ... + (StringLen(second) == 1 + ? "0" + second + : second) + + separator + + // + "" + // + ; + + // + return result; +} + +/** + * Converts an String Represetation of Time (00:00) to Date Time .. + * + * @param value: String ... + * + * @return ( datetime ) + */ +datetime ParseDateTimeFromTimeString(string value) +{ + // + datetime result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + // Check Signalling Time ... + MqlDateTime cTime; + bool isTimeRecieved = TimeCurrent(cTime); + if (!isTimeRecieved) + { + return result; + } + + // + // Split ... + string parts[]; + int partsCount = SplitContent( + parts, + value, + ":" + // + ); + if (!IsValidSize(partsCount)) + { + return result; + } + + // + int hour = 0; + int minute = 0; + if (partsCount >= 1) + { + hour = (int)(parts[0]); + } + if (partsCount >= 2) + { + minute = (int)(parts[1]); + } + + // + cTime.day_of_week = 0; + cTime.day_of_year = 0; + + // + cTime.hour = hour; + cTime.min = minute; + + // + result = StructToTime(cTime); + + // + return result; +} + +// +// Check Specific Time in Range of another Time ... +bool IsTimeInRange( + datetime currentTime = NULL, + datetime startTime = NULL, + datetime stopTime = NULL // +) +{ + // + bool result = false; + + // + // Normallize Current Time ... + currentTime = NormalizeTime(currentTime); + + // + result = !IsValid(startTime) && + !IsValid(stopTime); + if (result) + { + return result; + } + + // + result = IsValid(startTime) && + IsValid(stopTime); + if (!result) + { + // + result = IsValid(startTime) && + currentTime >= startTime; + + // + return result; + } + + // + result = currentTime >= startTime && + currentTime < stopTime; + + // + return result; +} +bool IsTimeInRange( + datetime currentTime, + string startTime, + string endTime // +) +{ + // + bool result = false; + + // + result = IsValid(startTime) && + IsValid(endTime); + if (!result) + { + // + // Here Since there isnot provide any + // data source we pass result as true ... + result = true; + return result; + } + + // + // Converts String Representation to Time ... + datetime st = ParseDateTimeFromTimeString(startTime); + datetime et = ParseDateTimeFromTimeString(endTime); + + // + result = IsTimeInRange( + currentTime, + st, + et // + ); + + // + return result; +} + +// +// END Time ... +// + +// +// START Price ... +// + +// +// Get 1 Pip in Price Value ... +double GetPipPrice( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double symbolPoint = GetPoints(mSymbol); + int symbolDigits = GetDigits(mSymbol); + + // + double result = symbolPoint; + if (symbolDigits == 3 || symbolDigits == 5) + { + result *= 10; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mType: ENUM_X_PRICE member, Price Type ... + * @param mOpen: double collection, Open Prices ... + * @param mHigh: double collection, High Prices ... + * @param mLow: double collection, Low Prices ... + * @param mClose: double collection, Close Prices ... + * @param barIndex: int, Index ... + * + * @return ( double ) + */ +double GetAppliedPrice( + ENUM_X_PRICE mType, // Type of Price Selection + const double &mOpen[], // Open Prices + const double &mHigh[], // High Preices + const double &mLow[], // Low Prices + const double &mClose[], // Close Prices + int barIndex // Bar Index +) +{ + // + double result = 0; + + // + switch (mType) + { + // + case X_PRICE_NONE: + result = 0; + break; + + // + case X_PRICE_HIGH: + result = mHigh[barIndex]; + break; + + // + case X_PRICE_OPEN: + result = mOpen[barIndex]; + break; + + // + case X_PRICE_CLOSE: + result = mClose[barIndex]; + break; + + // + case X_PRICE_LOW: + result = mLow[barIndex]; + break; + + // + case X_PRICE_UP: + result = MathMax(mOpen[barIndex], mClose[barIndex]); + break; + + // + case X_PRICE_DOWN: + result = MathMin(mOpen[barIndex], mClose[barIndex]); + break; + + // + case X_PRICE_MEDIAN: + result = ((mHigh[barIndex] + mLow[barIndex]) / 2.0); + break; + + // + case X_PRICE_BODY_MEDIAN: + result = ((mOpen[barIndex] + mClose[barIndex]) / 2.0); + break; + + // + case X_PRICE_TYPICAL: + result = ((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex]) / 3.0); + break; + + // + case X_PRICE_WEIGHTED: + result = (((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex] + mClose[barIndex]) / 4.0)); + break; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mType: ENUM_X_PRICE member, Price Type ... + * @param mOpen: double, Open Price ... + * @param mHigh: double, High Price ... + * @param mLow: double, Low Price ... + * @param mClose: double, Close Price ... + * @param barIndex: int, Index ... + * + * @return ( double ) + */ +double GetAppliedPrice( + ENUM_X_PRICE mType, // Type of Price Selection + double mOpen, // Open Prices + double mHigh, // High Preices + double mLow, // Low Prices + double mClose // Close Prices +) +{ + // + double result = 0; + + // + switch (mType) + { + // + case X_PRICE_NONE: + result = 0; + break; + + // + case X_PRICE_HIGH: + result = mHigh; + break; + + // + case X_PRICE_OPEN: + result = mOpen; + break; + + // + case X_PRICE_CLOSE: + result = mClose; + break; + + // + case X_PRICE_LOW: + result = mLow; + break; + + // + case X_PRICE_UP: + result = MathMax(mOpen, mClose); + break; + + // + case X_PRICE_DOWN: + result = MathMin(mOpen, mClose); + break; + + // + case X_PRICE_MEDIAN: + result = ((mHigh + mLow) / 2.0); + break; + + // + case X_PRICE_BODY_MEDIAN: + result = ((mOpen + mClose) / 2.0); + break; + + // + case X_PRICE_TYPICAL: + result = ((mHigh + mLow + mClose) / 3.0); + break; + + // + case X_PRICE_WEIGHTED: + result = (((mHigh + mLow + mClose + mClose) / 4.0)); + break; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ... + * @param barIndex: int, Specified Bar Index ... + * @param mType: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( double ) + */ +double GetAppliedPrice( + string mSymbol = NULL, // Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Period + int barIndex = 0, // Bar Index + ENUM_X_PRICE mType = X_PRICE_CLOSE // Type of Price Selection +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = IsValid(mType); + if (!has) + { + return result; + } + + // + double open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + + // + double high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + + // + double low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + + // + double close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + + // + // Retrieve Applied Price ... + result = GetAppliedPrice( + mType, + open, + high, + low, + close // + ); + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ... + * @param time: int, Specified Bar Time ... + * @param mType: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( double ) + */ +double GetAppliedPrice( + string mSymbol = NULL, // Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Period + datetime mTime = NULL, // Bar Time + ENUM_X_PRICE mType = X_PRICE_CLOSE // Type of Price Selection +) +{ + // + double result = 0; + + // + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + bool has = IsValid(mType); + if (!has) + { + return result; + } + + // + int barIndex = GetBarIndex( + mSymbol, + mPeriod, + mTime // + ); + has = IsValidIndex(barIndex); + if (!has) + { + return result; + } + + // + // Retrieve Applied Price ... + result = GetAppliedPrice( + mSymbol, + mPeriod, + barIndex, + mType // + ); + + // + return result; +} + +/** + * Calculate Price Boundary ... + * + * @param upper: double collection reference, Upper Boundary ... + * @param lower: double collection reference, Lower Boundary ... + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ... + * @param mMode: ENUM_X_BOUNDARY_PRICE member, Specified Boundary Mode ... + * @param mLength: int, Loopback Length of Bondary ... + * @param barIndex: int, Specified Bar Index ... + * @return ( int ) + */ +int GetPriceBoundary( + double &upper[], // Upper Boundary + double &lower[], // Lower Boundary + string mSymbol = NULL, // Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Period + ENUM_X_BOUNDARY_PRICE mMode = NULL, // Boundary Mode + int mLength = 1, // Length + int barIndex = 0 // Bar Index +) +{ + // + int result = 0; + + // + Clean(upper); + Clean(lower); + + // + // Normalize Args ... + mMode = NormalizeBoundary(mMode); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + mLength = NormalizeInt(mLength, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Prepare Boundary Price Types ... + ENUM_X_PRICE upperType = + mMode == X_BOUNDARY_PRICE_UP_DOWN + ? X_PRICE_UP + : mMode == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_NONE; + ENUM_X_PRICE lowerType = + mMode == X_BOUNDARY_PRICE_UP_DOWN + ? X_PRICE_DOWN + : mMode == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_NONE; + + // + // Check Boundary Type Validation ... + bool isValid = IsValid(lowerType) && + IsValid(upperType); + if (!isValid) + { + return result; + } + + // + // Loop through Loopbacks ... + int start = barIndex + mLength; + int end = barIndex; + for (int i = start; i >= end; i--) + { + // + double iUpper = GetAppliedPrice( + mSymbol, + mPeriod, + i, + upperType // + ); + double iLower = GetAppliedPrice( + mSymbol, + mPeriod, + i, + lowerType // + ); + + // + Add( + iUpper, + upper // + ); + + // + Add( + iLower, + lower // + ); + } + + // + result = ArraySize(upper); + + // + return result; +} + +// +// END Price ... +// + +// +// START Bar ... +// + +/** + * Retrieve Specific Bar's Time ... + * + * @param mSymbol: string, Provided Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ... + * @param barIndex: int, Provided Bar Index ... + * + * @return ( datetime ) + */ +datetime GetBarTime( + string mSymbol = NULL, // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + datetime result = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + return result; +} + +/** + * Retrieve Specific Bar's Index ... + * + * @param mSymbol: string, Provided Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ... + * @param barTime: datetime, Provided Bar Time ... + * + * @return ( datetime ) + */ +int GetBarIndex( + string mSymbol = NULL, // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + datetime barTime = NULL // Specify Bar Time +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + int result = iBarShift( + mSymbol, + mPeriod, + barTime // + ); + + // + return result; +} + +// +// END Bar ... +// + +// +// START Chart Info ... +// + +ENUM_CHART_MODE GetChartMode(long chartId = 0) +{ + return (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); +} + +color GetChartUpColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); +} + +color GetChartDownColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); +} + +color GetChartBullishColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); +} + +color GetChartBearishColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); +} + +color GetChartLineColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); +} + +color GetChartForeGroundColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); +} + +color GetChartBackGroundColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); +} + +color GetChartGridColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_GRID); +} + +color GetChartBidLineColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_BID); +} + +color GetChartAskLineColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_ASK); +} + +color GetChartStopColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); +} + +color GetChartVolumesColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); +} + +bool GetChartShowBidLine(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); +} + +bool GetChartShowAskLine(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); +} + +bool GetChartShowGrid(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); +} + +bool GetChartShowVolumes(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); +} + +bool GetChartShowTradeLevels(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); +} + +bool GetChartAutoScroll(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); +} + +bool GetChartQuickNavigation(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); +} + +// +// +// + +bool SetChartMode( + ENUM_CHART_MODE value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_MODE, value); +} + +bool SetChartShowBidLine( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_BID_LINE, value); +} + +bool SetChartShowAskLine( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, value); +} + +bool SetChartShowGrid( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_GRID, value); +} + +bool SetChartShowVolumes( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_VOLUMES, value); +} + +bool SetChartShowTradeLevels( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, value); +} + +bool SetChartAutoScroll( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_AUTOSCROLL, value); +} + +bool SetChartQuickNavigation( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, value); +} + +bool SetChartForeGroundColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, value); +} + +bool SetChartBackGroundColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, value); +} + +bool SetChartUpColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CHART_UP, value); +} + +bool SetChartDownColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, value); +} + +bool SetChartBullishColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, value); +} + +bool SetChartBearishColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, value); +} + +bool SetChartGridColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_GRID, value); +} + +bool SetChartBidLineColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_BID, value); +} + +bool SetChartAskLineColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_ASK, value); +} + +bool SetChartStopColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, value); +} + +bool SetChartLineColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, value); +} + +bool SetChartVolumesColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_VOLUME, value); +} + +// +// END Chart Info ... +// + +// diff --git a/BKPS/14040626/Libraries/x-saherelm.common.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..6b97b5d --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" +#include "../Libraries/x-saherelm.common.models.lib.mq5" +#include "../Libraries/x-saherelm.x-ohcl.lib.mq5" + +// +// Models ... + +// \ No newline at end of file diff --git a/BKPS/14040626/Libraries/x-saherelm.common.models.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.common.models.lib.mq5 new file mode 100644 index 0000000..c8e3186 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.common.models.lib.mq5 @@ -0,0 +1,392 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XModelsLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" + +// +// Use To Parse Symbols for +// Ignore Brokers Additional Suffixes ... +struct XSymbolParser +{ + // + string version; // Temp ... + + // + // Symbol Parsing ... + + // + // Forext ... + + // + bool IsEURUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsGBPUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "GBP", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURGBP(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "GBP" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsAUDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "AUD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURAUD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "AUD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsNZDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "NZD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURNZD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "NZD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Metals ... + + // + bool IsXAUUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAU", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsXAGUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAG", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Indexes ... + + // + bool IsDowJones(string symbol) + { + // + bool result = Contains( + "DowJones30", + symbol // + ); + + // + return result; + } + + // + // Oil ... + + // + bool IsBrent(string symbol) + { + // + bool result = Contains( + "BRENT", + symbol // + ); + + // + return result; + } + + // + // Symbol Finder ... + string GetEURUSDSymbol() + { + // + string result = NULL; + + // + string symbols[]; + int symbolsCount = GetAllSymbols( + symbols // + ); + if (!IsValidSize(symbolsCount)) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = symbols[i]; + if (IsEURUSD(iSymbol)) + { + // + result = iSymbol; + break; + } + } + + // + return result; + } +}; diff --git a/BKPS/14040626/Libraries/x-saherelm.draw.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ab7f39b --- /dev/null +++ b/BKPS/14040626/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/14040626/Libraries/x-saherelm.x-enums.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.x-enums.lib.mq5 new file mode 100644 index 0000000..3997e94 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.x-enums.lib.mq5 @@ -0,0 +1,1274 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XEnumsLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Price Type ... +// + +// +// Availables Price Types ... +enum ENUM_X_PRICE +{ + X_PRICE_NONE, // None + X_PRICE_HIGH, // High + X_PRICE_OPEN, // Open + X_PRICE_CLOSE, // Close + X_PRICE_LOW, // Low + X_PRICE_UP, // Body Up + X_PRICE_DOWN, // Body Down + X_PRICE_MEDIAN, // Median + X_PRICE_BODY_MEDIAN, // Body Median + X_PRICE_TYPICAL, // Typical + X_PRICE_WEIGHTED // Weighted +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_PRICE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_PRICE_NONE; + + // + return result; +} + +/** + * Converts Series Mode to ENUM_X_PRICE ... + * + * @param value: ENUM_SERIESMODE member ... + * + * @return ( ENUM_X_PRICE ) + */ +ENUM_X_PRICE ToXPrice(ENUM_SERIESMODE value) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (value) + { + // + // High ... + case MODE_HIGH: + result = X_PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = X_PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = X_PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = X_PRICE_CLOSE; + break; + } + + // + return result; +} + +/** + * Converts Applied Price to ENUM_X_PRICE ... + * + * @param value: ENUM_APPLIED_PRICE member ... + * + * @return ( ENUM_X_PRICE ) + */ +ENUM_X_PRICE ToXPrice(ENUM_APPLIED_PRICE value) +{ + // + ENUM_X_PRICE result = X_PRICE_NONE; + + // + switch (value) + { + // + case PRICE_HIGH: + result = X_PRICE_HIGH; + break; + + // + case PRICE_OPEN: + result = X_PRICE_OPEN; + break; + + // + case PRICE_CLOSE: + result = X_PRICE_CLOSE; + break; + + // + case PRICE_LOW: + result = X_PRICE_LOW; + break; + + // + case PRICE_MEDIAN: + result = X_PRICE_MEDIAN; + break; + + // + case PRICE_TYPICAL: + result = X_PRICE_TYPICAL; + break; + + // + case PRICE_WEIGHTED: + result = X_PRICE_WEIGHTED; + break; + } + + // + return result; +} + +/** + * Converts Price Type to Applied Price ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( ENUM_APPLIED_PRICE ) + */ +ENUM_APPLIED_PRICE ToAppliedPrice(ENUM_X_PRICE value) +{ + // + // Default ... + ENUM_APPLIED_PRICE result = PRICE_CLOSE; + + // + if (!IsValid(value) || + value == X_PRICE_UP || + value == X_PRICE_DOWN || + value == X_PRICE_BODY_MEDIAN) + { + return result; + } + + // + switch (value) + { + // + case X_PRICE_HIGH: + result = PRICE_HIGH; + break; + + // + case X_PRICE_OPEN: + result = PRICE_OPEN; + break; + + // + case X_PRICE_CLOSE: + result = PRICE_CLOSE; + break; + + // + case X_PRICE_LOW: + result = PRICE_LOW; + break; + + // + case X_PRICE_MEDIAN: + result = PRICE_MEDIAN; + break; + + // + case X_PRICE_TYPICAL: + result = PRICE_TYPICAL; + break; + + // + case X_PRICE_WEIGHTED: + result = PRICE_WEIGHTED; + break; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_PRICE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PRICE_NONE: + result = "None"; + break; + + // + case X_PRICE_HIGH: + result = "High"; + break; + + // + case X_PRICE_OPEN: + result = "Open"; + break; + + // + case X_PRICE_CLOSE: + result = "Close"; + break; + + // + case X_PRICE_LOW: + result = "Low"; + break; + + // + case X_PRICE_UP: + result = "Body Up"; + break; + + // + case X_PRICE_DOWN: + result = "Body Down"; + break; + + // + case X_PRICE_MEDIAN: + result = "Median"; + break; + + // + case X_PRICE_BODY_MEDIAN: + result = "Body Median"; + break; + + // + case X_PRICE_TYPICAL: + result = "Typical"; + break; + + // + case X_PRICE_WEIGHTED: + result = "Weighted"; + break; + } + + // + return result; +} + +// +// END Price Type ... +// + +// +// START Boundary Price Type ... +// + +// +// Available Boundary Price Types ... +enum ENUM_X_BOUNDARY_PRICE +{ + X_BOUNDARY_PRICE_NONE, // None + X_BOUNDARY_PRICE_UP_DOWN, // Up/Down + X_BOUNDARY_PRICE_HIGH_LOW, // High/Low +}; + +/** + * Validate ... + * + * @param value: ENUM_X_BOUNDARY_PRICE member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_BOUNDARY_PRICE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_BOUNDARY_PRICE_NONE; + + // + return result; +} +bool IsSpecifiedValid(ENUM_X_BOUNDARY_PRICE value) +{ + return IsValid(value); +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_BOUNDARY_PRICE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_BOUNDARY_PRICE value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + value = X_BOUNDARY_PRICE_NONE; + } + + // + result = EnumToString(value); + + // + return result; +} + +// +// END Boundary Price Type ... +// + +// +// START Direction ... +// + +// +// Directions ... +enum ENUM_X_DIRECTION +{ + X_DIRECTION_ALL, // All + X_DIRECTION_NONE, // None + X_DIRECTION_BULLISH, // Bullish + X_DIRECTION_BEARISH, // Bearish +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_DIRECTION_NONE; + + // + return result; +} +bool IsSpecifiedValid(ENUM_X_DIRECTION value) +{ + return IsValid(value); +} + +/** + * Validate value Has Specified Direction ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool HasDirection(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = IsValid(value) && + value != X_DIRECTION_ALL; + + // + return result; +} + +/** + * Check a Direction is Bullish or not ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} +bool IsSpecifiedBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Check a Direction is Bearish or not ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} +bool IsSpecifiedBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Converts Specified Direction to Opposit ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( ENUM_X_DIRECTION ) + */ +ENUM_X_DIRECTION Opposit(ENUM_X_DIRECTION value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!HasDirection(value)) + { + return result; + } + + // + result = + IsBullish(value) + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_DIRECTION value) +{ + // + string result = NULL; + + // + switch (value) + { + case X_DIRECTION_ALL: + result = "ALL"; + break; + case X_DIRECTION_NONE: + result = "NONE"; + break; + case X_DIRECTION_BULLISH: + result = "BULLISH"; + break; + case X_DIRECTION_BEARISH: + result = "BEARISH"; + break; + } + + // + return result; +} +string ToXString(ENUM_X_DIRECTION value) +{ + return ToString(value); +} +// +// END Direction ... +// + +// +// START Fibo Level ... +// + +// +// Fibonacci Levels ... +enum ENUM_X_FIBO_LEVELS +{ + X_FIBO_LEVEL_236, // 0.236 + X_FIBO_LEVEL_270, // 0.27 + X_FIBO_LEVEL_382, // 0.382 + X_FIBO_LEVEL_500, // 0.5 + X_FIBO_LEVEL_618, // 0.618 + X_FIBO_LEVEL_730, // 0.730 + X_FIBO_LEVEL_764, // 0.764 + X_FIBO_LEVEL_786, // 0.786 +}; + +// +// Extensions ... + +/** + * Converts To String ... + * + * @param value: ENUM_X_FIBO_LEVELS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_FIBO_LEVELS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = "0.236"; + break; + + // + case X_FIBO_LEVEL_270: + result = "0.270"; + break; + + // + case X_FIBO_LEVEL_382: + result = "0.382"; + break; + + // + case X_FIBO_LEVEL_500: + result = "0.500"; + break; + + // + case X_FIBO_LEVEL_618: + result = "0.618"; + break; + + // + case X_FIBO_LEVEL_730: + result = "0.730"; + break; + + // + case X_FIBO_LEVEL_764: + result = "0.764"; + break; + + // + case X_FIBO_LEVEL_786: + result = "0.786"; + break; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_FIBO_LEVELS member ... + * + * @return ( double ) + */ +double GetFiboLevelValue(ENUM_X_FIBO_LEVELS value) +{ + // + double result = 0; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = 0.236; + break; + + // + case X_FIBO_LEVEL_270: + result = 0.270; + break; + + // + case X_FIBO_LEVEL_382: + result = 0.382; + break; + + // + case X_FIBO_LEVEL_500: + result = 0.500; + break; + + // + case X_FIBO_LEVEL_618: + result = 0.618; + break; + + // + case X_FIBO_LEVEL_730: + result = 0.730; + break; + + // + case X_FIBO_LEVEL_764: + result = 0.764; + break; + + // + case X_FIBO_LEVEL_786: + result = 0.786; + break; + } + + // + return result; +} + +// +// END Fibo Level ... +// + +// +// START Swing Types ... +// + +// +// Swing Types ... +enum ENUM_X_SWING_TYPE +{ + X_SWING_NONE, // None + X_SWING_LOW, // Swing Low + X_SWING_HIGH, // Swing High +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_SWING_NONE; + + // + return result; +} +bool IsXValid(ENUM_X_SWING_TYPE value) +{ + return IsValid(value); +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_SWING_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_SWING_TYPE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SWING_NONE: + result = "None"; + break; + + // + case X_SWING_LOW: + result = "Swing Low"; + break; + + // + case X_SWING_HIGH: + result = "Swing High"; + break; + } + + // + return result; +} + +/** + * Converts To ENUM_SERIESMODE ... + * + * @param value: ENUM_X_SWING_TYPE member ... + * + * @return ( ENUM_SERIESMODE ) + */ +ENUM_SERIESMODE ToSeriesMode(ENUM_X_SWING_TYPE value) +{ + // + ENUM_SERIESMODE result = MODE_HIGH; + + // + switch (value) + { + // + case X_SWING_HIGH: + result = MODE_HIGH; + break; + + // + case X_SWING_LOW: + default: + result = MODE_LOW; + break; + } + + // + return result; +} + +// +// END Swing Types ... +// + +// +// START Period Method ... +// + +// +// Period Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + X_PERIOD_NONE, // None + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_PERIOD_METHOD member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_PERIOD_METHOD value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_PERIOD_NONE; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_PERIOD_METHOD member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_PERIOD_METHOD value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PERIOD_NONE: + result = "None"; + break; + + // + case X_PERIOD_AUTO: + result = "Auto Select"; + break; + + // + case X_PERIOD_MANUALLY: + result = "Manually"; + break; + } + + // + return result; +} + +// +// END Period Method ... +// + +// +// START Market Cycles ... +// + +// +// Market Cycles ... +enum ENUM_X_MARKET_CYCLES +{ + X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle + X_MARKET_CYCLE_SHORT, // Short Cycle + X_MARKET_CYCLE_MEDIUM, // Medium Cycle + X_MARKET_CYCLE_LONG, // Long Cycle + X_MARKET_CYCLE_HIND, // Hind Cycle +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_MARKET_CYCLES member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_X_MARKET_CYCLES value) +{ + return IsValid(value); +} + +/** + * Converts an String to it's related Market Cycle ... + * + * @param value: string ... + * + * @return ( ENUM_X_MARKET_CYCLES ) + */ +ENUM_X_MARKET_CYCLES ToCycle(string value) +{ + // + ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetAllMarketCycles(cycles); + for (int i = 0; i < count; i++) + { + // + ENUM_X_MARKET_CYCLES iCycle = cycles[i]; + string iStr = ToString(iCycle); + + // + if (value == iStr) + { + // + result = iCycle; + break; + } + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_MARKET_CYCLES member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_MARKET_CYCLES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_MARKET_CYCLE_UNKNOWN: + result = "Unknown Cycle"; + break; + + // + case X_MARKET_CYCLE_SHORT: + result = "Short Cycle"; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + result = "Medium Cycle"; + break; + + // + case X_MARKET_CYCLE_LONG: + result = "Long Cycle"; + break; + + // + case X_MARKET_CYCLE_HIND: + result = "Hind Cycle"; + break; + } + + // + return result; +} +string ToXString(ENUM_X_MARKET_CYCLES value) +{ + return ToString(value); +} + +/** + * Retrieve All Availabled Market Cycles ... + * + * @param cycles: ENUM_X_MARKET_CYCLES member collection ... + * + * @return ( int ) + */ +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &cycles[]) +{ + // + ZeroMemory(cycles); + ArrayResize(cycles, 0); + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_UNKNOWN; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_SHORT; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_MEDIUM; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_LONG; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_HIND; + + // + int result = ArraySize(cycles); + + // + return result; +} + +// +// END Market Cycles ... +// + +// +// START Week Days ... +// + +// +// Week Days ... +enum ENUM_X_WEEK_DAYS +{ + X_WEEK_DAY_NONE = -1, // None + X_WEEK_DAY_SUNDAY = 0, // Sunday + X_WEEK_DAY_MONDAY = 1, // Monday + X_WEEK_DAY_TUESDAY = 2, // Tuesday + X_WEEK_DAY_WEDNESDAY = 3, // Wednesday + X_WEEK_DAY_THURSDAY = 4, // Thursday + X_WEEK_DAY_FRIDAY = 5, // Friday + X_WEEK_DAY_SATURDAY = 6, // Saturday +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_WEEK_DAYS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_WEEK_DAYS value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_WEEK_DAY_NONE + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_WEEK_DAYS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_WEEK_DAYS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_WEEK_DAY_NONE: + result = "None"; + break; + + // + case X_WEEK_DAY_SUNDAY: + result = "Sunday"; + break; + + // + case X_WEEK_DAY_MONDAY: + result = "Monday"; + break; + + // + case X_WEEK_DAY_TUESDAY: + result = "Tuesday"; + break; + + // + case X_WEEK_DAY_WEDNESDAY: + result = "Wednesday"; + break; + + // + case X_WEEK_DAY_THURSDAY: + result = "Thursday"; + break; + + // + case X_WEEK_DAY_FRIDAY: + result = "Friday"; + break; + + // + case X_WEEK_DAY_SATURDAY: + result = "Saturday"; + break; + } + + // + return result; +} + +// +// END Week Days ... +// + +// +// START Ma Methods ... +// + +// +// Ma Methods ... +enum ENUM_X_MA_METHOD +{ + X_MA_MODE_NONE, // None + X_MA_MODE_SMA, // SMA + X_MA_MODE_EMA, // EMA + X_MA_MODE_LWMA, // LWMA + X_MA_MODE_SMMA, // SMMA +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_MA_METHOD member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_MA_METHOD value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MA_MODE_NONE + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_MA_METHOD member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_MA_METHOD value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_MA_MODE_NONE: + result = "None"; + break; + + // + case X_MA_MODE_SMA: + result = "SMA"; + break; + + // + case X_MA_MODE_EMA: + result = "EMA"; + break; + + // + case X_MA_MODE_LWMA: + result = "LWMA"; + break; + + // + case X_MA_MODE_SMMA: + result = "SMMA"; + break; + } + + // + return result; +} + +// +// END Ma Methods ... +// + +// \ No newline at end of file diff --git a/BKPS/14040626/Libraries/x-saherelm.x-guard.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.x-guard.lib.mq5 new file mode 100644 index 0000000..e0e4c05 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.x-guard.lib.mq5 @@ -0,0 +1,214 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XGuardLib +// Description: All models related to Guard ... +// +// +// 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" + +// +// Enumeration ... + +// +// Guard Actions ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_NONE, // Nothing to Do + X_GUARD_ACTION_CLOSE, // Close Specified Position + X_GUARD_ACTION_CLOSE_ALL, // Close All Positions + X_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions + X_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position + X_GUARD_ACTION_CLOSE_IN_LOSTS, // Close All In Lost Position + X_GUARD_ACTION_CLOSE_IN_PROFITS, // Close All In Profit Position + X_GUARD_ACTION_CLOSE_IN_LOST_LONGS, // Close All In Lost Long Position + X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS, // Close All In Profit Long Position + X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS, // Close All In Lost Short Position + X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT, // Close All In Profit Short Position + X_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position + X_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position + X_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position + X_GUARD_ACTION_HEDGE, // Hedge Specified Positions +}; + +// +// Definitions ... + +// +// Model a Guard Action ... +struct XGuard +{ + // + // Props ... + ENUM_X_GUARD_ACTIONS action; + datetime time; + + // + string symbol; + string provider; + ENUM_TIMEFRAMES period; + + // + // Specified Position ... + ulong ticket; + + // + // Partial Close ... + double volumeMultiplier; + + // + // SL Trial ... + double sl; + + // + // TP Trial ... + double tp; + + // + bool force; + + // + // Constructor ... + XGuard() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + action = X_GUARD_ACTION_NONE; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + + // + force = false; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(time) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(action) && + IsSpecifiedValid(provider) + // + ; + + if (!result) + { + return result; + } + + // + // Validate Model Based On Specified Guard Actions ... + + // + return result; + } +}; + +// +// Extensions ... + +// +bool IsValid(ENUM_X_GUARD_ACTIONS item) +{ + // + bool result = false; + + // + result = item != X_GUARD_ACTION_NONE; + + // + return result; +} +bool IsSpecifiedValid(ENUM_X_GUARD_ACTIONS item) +{ + return IsValid(item); +} + +/** + * Add Guard to Collection ... + * + * @param guard: XGuard instance ... + * @param guards: XGuard instance Collection ... + * + * @return ( int ) + */ +int AddGuard( + XGuard &guard, + XGuard &guards[] // +) +{ + // + int result = 0; + + // + if (!guard.IsValid()) + { + return result; + } + + // + AddRef( + guard, + guards // + ); + + // + result = ArraySize(guards); + + // + return result; +} diff --git a/BKPS/14040626/Libraries/x-saherelm.x-ohcl.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.x-ohcl.lib.mq5 new file mode 100644 index 0000000..b654083 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.x-ohcl.lib.mq5 @@ -0,0 +1,2214 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XOHCLLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + long volume; + double spread; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + open = NormalizePrice(open, mSymbol); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + close = NormalizePrice(close, mSymbol); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + high = NormalizePrice(high, mSymbol); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + low = NormalizePrice(low, mSymbol); + + // + spread = iSpread( + mSymbol, + mPeriod, + barIndex // + ); + spread = NormalizePrice(spread, mSymbol); + + // + volume = iTickVolume( + mSymbol, + mPeriod, + barIndex // + ); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + // Tools ... + + // + void Clean() + { + // + low = 0; + high = 0; + open = 0; + close = 0; + spread = 0; + volume = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + + // + ZeroMemory(this); + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + low > 0 && + high > 0 && + open > 0 && + close > 0 && + volume > 0 + // + // TODO: Fix in Some Cases for Zero Spread ... + // spread > 0 && + // + ; + + // + return result; + } + + // + int TotalBars() + { + // + int result = 0; + + // + result = iBars( + symbol, + period // + ); + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + return GetAppliedPrice( + mPType, + open, + high, + low, + close // + ); + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mType = ToXPrice(mMode); + + // + return GetPrice(mType); + } + + // + // Calculate Applied Price ... + double GetPrice(ENUM_APPLIED_PRICE mPType) + { + // + ENUM_X_PRICE mType = ToXPrice(mPType); + + // + return GetPrice(mType); + } + + // + // Find Specific Price ... + bool FindHigherPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice > price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindLowerPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice < price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // Get Direction of Bar ... + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isBullish = IsBullish(); + bool isBearish = IsBearish(); + + // + result = + isBullish && isBearish + ? X_DIRECTION_ALL + : !isBullish && !isBearish + ? X_DIRECTION_NONE + : isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Find Next Bar Time ... + datetime NextAt() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time + prSeconds; + + // + return result; + } + + // + // Find Prev Bar Time ... + datetime BeforeOn() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time - prSeconds; + + // + return result; + } + + // + // Calculate Last Bar Open Time in Smaller Period ... + datetime GetLastBarTimeOfPeriod( + ENUM_TIMEFRAMES smallerPeriod // + ) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(period); + int destSeconds = PeriodSeconds(smallerPeriod); + if (destSeconds >= sourceSeconds) + { + // + result = time; + return result; + } + + // + result = (datetime)((((int)time) + sourceSeconds) - destSeconds); + + // + return result; + } + + // + // Calculate Close Time ... + datetime GetCloseTime() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int seconds = PeriodSeconds(period); + + // + result = (datetime)(((int)time) + seconds); + + // + return result; + } + + // + bool BarAt( + int index, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (index < 0) + { + index = 0; + } + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool BarIn( + ENUM_TIMEFRAMES _period, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid() && + IsSpecifiedValid(_period); + if (!result) + { + return result; + } + + // + int index = Index(_period); + result = bar.Init( + symbol, + _period, + index // + ); + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + int Index(datetime value) + { + // + int result = -1; + + // + value = NormalizeTime(value); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + value // + ); + + // + return result; + } + + // + int Index(ENUM_TIMEFRAMES value) + { + // + int result = -1; + + // + result = IsValid() && + IsSpecifiedValid(value); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + value, + time // + ); + + // + return result; + } + + // + bool GetNextBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + result = idx > 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + this.symbol, + this.period, + idx - 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool GetPreviousBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + + // + result = bar.Init( + this.symbol, + this.period, + idx + 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool HasFiboPressure( + ENUM_X_DIRECTION forDir, + ENUM_X_FIBO_LEVELS level = X_FIBO_LEVEL_382 // + ) + { + // + bool result = false; + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsSpecifiedBullish(forDir); + bool isBearish = IsSpecifiedBearish(forDir); + + // + double fiboLevelValue = GetFibonacciLevel( + high, + low, + level, + forDir // + ); + + // + isBullish = + isBullish && + GetDown() > fiboLevelValue; + isBearish = + isBearish && + GetUp() < fiboLevelValue; + + // + result = isBullish || + isBearish; + + // + return result; + } + + // + bool IsRejected( + double price, + ENUM_X_DIRECTION forDir, + bool forceType = false, + bool forcePressure = false // + ) + { + // + bool result = false; + + // + result = IsValid() && + price > 0 && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = + IsSpecifiedBullish(forDir) && + low < price && + GetDown() > price; + + // + bool isBearish = + IsSpecifiedBearish(forDir) && + high > price && + GetUp() < price; + + // + if (forceType) + { + // + isBullish = + isBullish && + IsBullish(); + + // + isBearish = + isBearish && + IsBearish(); + } + + // + if (forcePressure) + { + // + isBullish = + isBullish && + HasFiboPressure(forDir); + + // + isBearish = + isBearish && + HasFiboPressure(forDir); + } + + // + result = isBullish || + isBearish; + + // + return result; + } + + // + bool IsBreaked( + double price, + ENUM_X_DIRECTION forDir, + ENUM_X_FIBO_LEVELS fibLevel = X_FIBO_LEVEL_500, + ENUM_X_BOUNDARY_PRICE boundaryType = X_BOUNDARY_PRICE_UP_DOWN // + ) + { + // + bool result = false; + + // + result = IsValid() && + price > 0 && + HasDirection(forDir) && + IsSpecifiedValid(boundaryType); + if (!result) + { + return result; + } + + // + bool isUpDownPriceType = boundaryType == X_BOUNDARY_PRICE_UP_DOWN; + + // + bool isBullish = + IsBullish() && + low < price && + high > price && + IsSpecifiedBullish(forDir); + + // + bool isBearish = + IsBearish() && + low < price && + high > price && + IsSpecifiedBearish(forDir); + + // + result = isBullish || + isBearish; + if (result) + { + // + // Calculate Range ... + double range = + isUpDownPriceType + ? GetBody() + : GetRange(); + + // + // Apply Edge Range ... + double iReqRange = + (range / 100) * (GetFiboLevelValue(fibLevel) * 100); + + // + // Calculate Boundary Price ... + double iBoundary = + isUpDownPriceType + ? isBullish + ? GetUp() + : GetDown() + : isBullish + ? high + : low; + + // + // Detect Breaked Value ... + + // + double breakedPrice = + isBullish + ? (high - price) + : (price - low); + + // + result = + breakedPrice >= iReqRange; + } + + // + 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; + } + + // + // Swing Detection ... + + // + int FindSwing( + ENUM_X_SWING_TYPE type, + int shoulders = 3 // + ) + { + // + int result = -1; + + // + // Validate ... + bool isValid = IsValid() && + IsXValid(type); + if (!isValid) + { + return result; + } + + // + // Find Next Swing ... + result = FindXSwing( + type, + symbol, + period, + Index(), + shoulders // + ); + + // + return result; + } + + // + int FindNextSwing( + ENUM_X_SWING_TYPE type, + int shoulders = 3 // + ) + { + // + int result = -1; + + // + // Validate ... + bool isValid = IsValid() && + IsXValid(type); + if (!isValid) + { + return result; + } + + // + // Find Next Swing ... + result = FindXSwing( + type, + symbol, + period, + Index() + 1, + shoulders // + ); + + // + return result; + } + + // + bool FindSwingBar( + ENUM_X_SWING_TYPE type, + XOHCL &swingBar, + int shoulders = 3 // + ) + { + // + bool result = false; + + // + // Prepare ... + swingBar.Clean(); + + // + // Validate ... + result = IsValid() && + IsXValid(type); + if (!result) + { + return result; + } + + // + // Find Next Swing ... + int idx = FindXSwing( + type, + symbol, + period, + Index(), + shoulders // + ); + result = IsValidIndex(idx); + if (!result) + { + return result; + } + + // + result = swingBar.Init( + symbol, + period, + idx // + ); + + // + return result; + } + + // + bool FindNextSwingBar( + ENUM_X_SWING_TYPE type, + XOHCL &swingBar, + int shoulders = 3 // + ) + { + // + bool result = false; + + // + // Prepare ... + swingBar.Clean(); + + // + // Validate ... + result = IsValid() && + IsXValid(type); + if (!result) + { + return result; + } + + // + // Find Next Swing ... + int idx = FindXSwing( + type, + symbol, + period, + Index() + 1, + shoulders // + ); + result = IsValidIndex(idx); + if (!result) + { + return result; + } + + // + result = swingBar.Init( + symbol, + period, + idx // + ); + + // + return result; + } + + // + // Other ... + string GetTag(string prefix = "") + { + // + string result = NULL; + + // + result = + (IsSpecifiedValid(prefix) + ? prefix + "_" + : "") + + "XOHCL_" + symbol + "_" + ToXString(period) + "_" + ToFormatString(time); + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToXString(open) + "),H(" + ToXString(high) + "),C(" + ToXString(close) + "),L(" + ToXString(low) + "))"; + + // + return result; + } +}; + +// +// Models ... + +// +// Model a Bar Remains Time ... +struct XBarRemainsTime +{ + // + int days; + int hours; + int minutes; + int seconds; + + // + // Constructor ... + XBarRemainsTime() + { + Clean(); + } + + // + // Always Calculate Current 0 Bar Timing ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetBarTime( + mSymbol, + mPeriod, + 0 + // + ); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + days = 0; + hours = 0; + minutes = 0; + seconds = 0; + + // + ZeroMemory(this); + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToXString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToXString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToXString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + int xMinute; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xMinute = -1; + xDayOfWeek = -1; + xForWeekDay = -1; + + // + ZeroMemory(this); + } + + // + // Detecting New Minute ... + bool IsNewMinute() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.min != xMinute; + if (result) + { + xMinute = timeStruct.min; + } + + // + return result; + } + + // + // Detecting New Houre ... + bool IsNewHour() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.hour != xHour; + if (result) + { + xHour = timeStruct.hour; + } + + // + return result; + } + + // + // Detecting New Day ... + bool IsNewDay() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.day_of_year != xDay; + if (result) + { + xDay = timeStruct.day_of_year; + } + + // + return result; + } + + // + // Detecting New Week ... + bool IsNewWeek() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Week ... + // Since Week Starts From Monday in Forex World ... + // we Calculate Start of Week by 1-Monday ... + result = + xDayOfWeek == -1 && + xForWeekDay == -1 + ? true + : timeStruct.day_of_week == 1 && + timeStruct.day_of_year > xForWeekDay; + + // + xForWeekDay = timeStruct.day_of_year; + xDayOfWeek = timeStruct.day_of_week; + + // + return result; + } + + // + // Detecting End Of Week ... + bool IsWeekEnd() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check WeekEnd ... + // Since Week Starts From Monday in Forex World ... + // we Calculate End of Week by 5-Friday ... + result = + xDayOfWeek != -1 && + timeStruct.day_of_week == 5 && + timeStruct.hour == 23 && + timeStruct.min == 59 && + timeStruct.sec == 59; + + // + return result; + } + + // + // Detecting New Month ... + bool IsNewMonth() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.mon != xMonth; + if (result) + { + xMonth = timeStruct.mon; + } + + // + return result; + } +}; + +// +// Tracking Bars on Specified Environment ... +struct XBarTracker +{ + // + string symbol; // Tracking Symbol + ENUM_TIMEFRAMES period; // Tracking Time Frame + + // + int lastTrackedBar; // Last Tracked Bar ... + + // + bool waitsUntilNext; // Waits Until Next Bar ... + + // + // Constructor ... + XBarTracker() + { + Clean(); + } + + // + // Initializer ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + this.symbol = mSymbol; + this.period = mPeriod; + + // + this.lastTrackedBar = 0; + + // + result = true; + + // + return result; + } + + // + // Retrieve all Bars ... + int CountBars() + { + // + return iBars( + symbol, + period + // + ); + } + + // + // Check if it's New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + int currentBars = CountBars(); + + // + result = currentBars > lastTrackedBar; + if (result) + { + lastTrackedBar = currentBars; + } + + // + return result; + } + + // + bool CanProcessBar() + { + // + bool _isInTestMode = IsRunningOnTestMode(); + + // + bool isNewBar = IsNewBar(); + + // + bool result = + _isInTestMode + ? isNewBar + : !waitsUntilNext + ? true + : isNewBar; + if (result && waitsUntilNext) + { + waitsUntilNext = false; + } + + // + return result; + } + + // + void Waits() + { + this.waitsUntilNext = true; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + + // + ZeroMemory(this); + } + + // + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + NormalizeTime(time); + + // + int barIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + result = barIndex >= 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + barIndex // + ); + + // + return result; + } + + // + int Index(datetime time = NULL) + { + // + int result = 0; + + // + NormalizeTime(time); + + // + result = iBarShift( + symbol, + period, + time, + false // + ); + + // + return result; + } +}; + +// +// Extensions ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &bars[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + int from = 0, // Start Bar Index + int count = 1 // Number of Bars +) +{ + // + int result = 0; + + // + from = NormalizeInt(from); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int total = Bars( + mSymbol, + mPeriod // + ); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + Clean(bars); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + bars // + ); + } + } + + // + result = ArraySize(bars); + + // + return result; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &bars[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + datetime from = NULL, // Start Bar Time + int count = 1 // Number of Bars +) +{ + // + from = NormalizeTime(from); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = GetBarIndex( + mSymbol, + mPeriod, + from // + ); + + // + return GetBars( + bars, + mSymbol, + mPeriod, + barIndex, + count // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..5318ee4 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -0,0 +1,1363 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Extensions ... + +/** + * Get Oldest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetOldest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetYoungest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetHighest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetLowest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Find Specified Box Index inside a Collection of Boxes ... + * + * @param box: XBoxZone instance Reference ... + * @param boxes: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +bool FindIndex( + int &index, + XBoxZone &item, + XBoxZone &items[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(items); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = items[i]; + + // + bool isSame = item.IsSameAs(iBox); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} +bool FindIndex( + int &index, + XDirectionShift &item, + XDirectionShift &items[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(items); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XDirectionShift iItem = items[i]; + + // + bool isSame = item.IsSameAs(iItem); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Remove Specified Box from Collection ... + */ +bool Remove( + XBoxZone &item, + XBoxZone &items[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(items); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + items // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + items, + idx, + 1 // + ); + + // + return result; +} +bool Remove( + XDirectionShift &item, + XDirectionShift &items[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(items); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + items // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + items, + idx, + 1 // + ); + + // + return result; +} + +/** + * Remove Specified Box from Collection ... + */ +int Removes( + XBoxZone &items[], + XBoxZone &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + int idx = -1; + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + result++; + } + } + } + + // + return result; +} +int Removes( + XDirectionShift &items[], + XDirectionShift &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + int idx = -1; + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + result++; + } + } + } + + // + return result; +} + +/** + * Add items reference into source Collection only if it's not Exists ...alignas + * + * @param item: XBoxZone instance Reference, Specified Item to Add ... + * @param sources: XBoxZone instance Reference Collection, Source Items Collection ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XBoxZone &item, + XBoxZone &sources[], + int maxAllowed = 50 // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = item.IsValid(); + if (!result) + { + return result; + } + + // + // Check Item Exists or not ... + int idx = -1; + bool isExists = FindIndex( + idx, + item, + sources // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + AddRef( + item, + sources //; + ); + + // + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} +bool AddIfNotExists( + XDirectionShift &item, + XDirectionShift &sources[], + int maxAllowed = 50 // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = item.IsValid(); + if (!result) + { + return result; + } + + // + // Check Item Exists or not ... + int idx = -1; + bool isExists = FindIndex( + idx, + item, + sources // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + AddRef( + item, + sources //; + ); + + // + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +/** + * Add items Collection reference Members into source Collection only if it's not Exists ...alignas + * + * @param items: XBoxZone instance Reference Collection, Specified Items to Add ... + * @param sources: XBoxZone instance Reference Collection, Source Items Collection ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( int ) + */ +int AddIfNotExists( + XBoxZone &items[], + XBoxZone &sources[], + int maxAllowed = 50 // +) +{ + // + 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; + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} +int AddIfNotExists( + XDirectionShift &items[], + XDirectionShift &sources[], + int maxAllowed = 50 // +) +{ + // + 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; + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +// +// +// + +/** + * Validate Boxes ... + * @param box: XBoxZone instance reference for Validate ... + * @param barIndex: int, Bar Index ... + * @param barsLength: int, Bars Length for Validation ... + * + * @return ( bool ) + */ +bool IsBoxValid( + XBoxZone &box, + int barIndex = 0, + int barsLength = 3 // +) +{ + // + bool result = false; + + // + // Normalize Bar Index ... + barIndex = NormalizeInt(barIndex, 0); + barsLength = NormalizeInt(barsLength, 1); + + // + // Ceck Input Box is Valid ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + // Check Input Box is Breaked or not ... + // Breaktion Found using Counting Over/Under Close Bars ... + bool isBullish = box.IsBullish(); + double appliedPrice = box.GetInDirectionalPrice(); + result = NotEmptyZero(appliedPrice); + if (!result) + { + return result; + } + + // + int toIDX = box.ToIndex(); + + // + XOHCL iBar; + int edgeBreakes = 0; + for (int i = barIndex; i <= toIDX; i++) + { + // + // Initialize Indexed Bar ... + result = iBar.Init( + box.symbol, + box.period, + i // + ); + + // + // Checking Price ... + result = + // + // Checking Bar Validation ... + result && + // + // Checking Price Breaked or not ... + (isBullish + ? iBar.close < box.lower + : iBar.close > box.upper); + if (result) + { + edgeBreakes++; + } + else + { + edgeBreakes = 0; + } + + // + result = edgeBreakes >= barsLength; + if (result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + // return true; + + // + result = + edgeBreakes < barsLength; + + // + return result; +} + +// +void SortBoxes( + XBoxZone &items[], + int maxAllowed = 0 // +) +{ + // + int idx = -1; + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + idx = GetOldest(tmp); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + AddRef( + iBox, + items // + ); + } + + // + if (maxAllowed > 0) + { + // + CleanupArray( + items, + maxAllowed // + ); + } + + // + Clean(tmp); +} + +/** + * Check a BaxHas Valid Place for Specified Bar ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * #param box: XBoxZone instance reference, Specified Box ... + * + * @return ( bool ) + */ +bool IsBoxPlaceValidForBar( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + box.IsBullish() + ? bar.low > box.upper + : bar.high < box.upper; + + // + return result; +} + +// +void ValidateBoxes( + XBoxZone &boxes[], + int barIndex = 0, + int barsLength = 3, + bool forceSorting = false, + int maxAllowed = 0 // +) +{ + // + bool has = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + barsLength = NormalizeInt(barsLength, 3); + + // + // Validate Args ... + has = HasChild(boxes); + if (!has) + { + return; + } + + // + // Copy Boxes to tmp ... + XBoxZone tmp[]; + Copy( + boxes, + tmp // + ); + Clean(boxes); + + // + // Looping Through Exists Boxes ... + while (HasChild(tmp)) + { + // + // Select Indexed Box ... + XBoxZone iBox = tmp[0]; + + // + // Remove Indexed Box ... + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + // Check Box Validating ... + has = IsBoxValid( + iBox, + barIndex, + barsLength // + ); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + } + + // + // Sorting ... + if (forceSorting) + { + // + // Check Has Result or not ... + has = HasChild(boxes); + if (has) + { + // + // Sorting ... + SortBoxes( + boxes, + maxAllowed // + ); + } + } + + // +} + +/** + * Converts a Bar to Support Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param toTime: datetime, Specified Box to Time ... + * + * @return ( bool ) + */ +bool ToSupportBox( + XOHCL &bar, + XBoxZone &box, + datetime toTime = NULL // +) +{ + // + bool result = false; + + // + box.Clean(); + toTime = NormalizeTime(toTime); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + box.to = toTime; + box.from = bar.time; + box.lower = bar.low; + box.symbol = bar.symbol; + box.period = bar.period; + box.upper = bar.GetDown(); + box.dir = X_DIRECTION_BULLISH; + box.type = "Support"; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; +} + +/** + * Converts a Bar to Resistance Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param toTime: datetime, Specified Box to Time ... + * + * @return ( bool ) + */ +bool ToResistanceBox( + XOHCL &bar, + XBoxZone &box, + datetime toTime = NULL // +) +{ + // + bool result = false; + + // + box.Clean(); + toTime = NormalizeTime(toTime); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + box.to = toTime; + box.from = bar.time; + box.upper = bar.high; + box.symbol = bar.symbol; + box.period = bar.period; + box.lower = bar.GetUp(); + box.dir = X_DIRECTION_BEARISH; + box.type = "Resistance"; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/Libraries/x-saherelm.x-poi.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.x-poi.lib.mq5 new file mode 100644 index 0000000..77140d2 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.x-poi.lib.mq5 @@ -0,0 +1,725 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + +// +struct XBoxZone +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime at; + datetime from; + datetime to; + + // + string type; + ENUM_X_DIRECTION dir; + + // + // Constructor ... + XBoxZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + to = NULL; + at = 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 && + IsSpecifiedValid(to) && + upper >= lower && + IsSpecifiedValid(from) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) + // + ; + + // + return result; + } + + /** + * Check Box is Bullish or not ... + * + * @return ( bool ) + */ + bool IsBullish() + { + return IsValid() && + IsSpecifiedBullish(dir); + } + + /** + * Check Box is Bearish or not ... + * + * @return ( bool ) + */ + bool IsBearish() + { + return IsValid() && + IsSpecifiedBearish(dir); + } + + /** + * Clone Box by Provided Source ... + * + * @return ( bool ) + */ + bool Clone(XBoxZone &source) + { + // + bool result = false; + + // + Clean(); + result = source.IsValid(); + if (!result) + { + return result; + } + + // + // Filling Props ... + to = source.to; + dir = source.dir; + from = source.from; + type = source.type; + upper = source.upper; + lower = source.lower; + symbol = source.symbol; + period = source.period; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + /** + * Check Box is Same as Other ... + * + * @param item: XBoxZone instance Resource ... + * + * @return ( bool ) + */ + bool IsSameAs(XBoxZone &item) + { + // + return IsValid() && + item.IsValid() && + dir == item.dir && + from == item.from && + type == item.type && + lower == item.lower && + upper == item.upper && + symbol == item.symbol && + period == item.period; + } + + /** + * Retrieve Box Age ... + * + * @param forPeriod: ENUM_TIMEFRAMES member ... + * + * @return ( int ) + */ + int GetAge( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + result = iBarShift( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Calculate Box Middle Price ... + * + * @return ( double ) + */ + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + double diffAvg = (upper - lower) / 2; + result = lower + diffAvg; + result = NormalizePrice(result, symbol); + + // + return result; + } + + /** + * Calculate Box Leg N Price ... + * N default is 2 + * + * @param leg: int ... + * + * @return ( double ) + */ + double GetLeg(int leg = 2) + { + // + double result = 0; + + // + leg = NormalizeInt(leg, 2); + + // + if (!IsValid()) + { + return result; + } + + // + double range = (upper - lower) * leg; + result = + IsBullish() + ? upper + range + : lower - range; + result = NormalizePrice(result, symbol); + + // + return result; + } + + /** + * Calculate Box Range ... + * + * @return ( double ) + */ + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (upper - lower); + result = NormalizePrice(result, symbol); + + // + return result; + } + + /** + * Retrieve Box Applied Price ... + * + * @return ( double ) + */ + double GetDirectionalPrice() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? upper + : lower; + + // + return result; + } + + /** + * Retrieve Box Breaked Price ... + * + * @return ( double ) + */ + double GetInDirectionalPrice() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? lower + : upper; + + // + return result; + } + + /** + * To Bar Index ... + * + * @return ( int ) + */ + int ToIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + to // + ); + + // + return result; + } + + /** + * Retrieve To Bar ... + * + * @return ( bool ) + */ + bool ToBar(XOHCL &bar) + { + // + bool result = false; + + // + bar.Clean(); + + // + int idx = ToIndex(); + + // + result = + IsValid() && + IsValidIndex(idx); + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + idx // + ); + + // + return result; + } + + /** + * From Bar Index ... + * + * @return ( int ) + */ + int FromIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Retrieve From Bar ... + * + * @return ( bool ) + */ + bool FromBar(XOHCL &bar) + { + // + bool result = false; + + // + bar.Clean(); + + // + int idx = FromIndex(); + + // + result = + IsValid() && + IsValidIndex(idx); + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + idx // + ); + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + int digits = GetDigits(symbol); + double nUpper = NormalizeDouble(NormalizePrice(upper, symbol), digits); + double nLower = NormalizeDouble(NormalizePrice(lower, symbol), digits); + + // + string typeStr = IsSpecifiedValid(type) + ? type + : "XBOX"; + string result = + // + typeStr + "_" + + ToString(dir) + "_" + + symbol + "_" + + ToXString(period) + "_" + + ToXString(nUpper) + "_" + + ToXString(nLower) + // + ; + + // + return result; + } + + /** + * Retrieve Unique Middle Identifier ... + * + * @return ( string ) + */ + string GetMiddleTag() + { + // + int digits = GetDigits(symbol); + double nMid = NormalizeDouble(NormalizePrice(GetMid(), symbol), digits); + + // + string typeStr = IsSpecifiedValid(type) + ? type + : "XBOX"; + string result = + // + typeStr + "_" + + "Mid_" + + ToString(dir) + "_" + + symbol + "_" + + ToXString(period) + "_" + + ToXString(nMid) + // + ; + + // + return result; + } +}; + +// +struct XDirectionShift +{ + // + // Props ... + string type; + datetime at; + double after; + double before; + string symbol; + ENUM_TIMEFRAMES period; + ENUM_X_DIRECTION shiftTo; + + // + // Constructor ... + XDirectionShift() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + at = NULL; + after = 0; + before = 0; + type = NULL; + symbol = NULL; + period = NULL; + shiftTo = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + after > 0 && + IsSpecifiedValid(at) && + IsSpecifiedValid(type) && + after != before && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + HasDirection(shiftTo); + + // + return result; + } + + // + // Get Bar Index of Direction Shift ... + int Index() + { + // + int result = -1; + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + // Retrieve Bar Index ... + result = GetBarIndex( + symbol, + period, + at // + ); + + // + return result; + } + + // + // Get At Bar ... + bool AtBar(XOHCL &bar) + { + // + bool result = false; + + // + // Normalize ... + bar.Clean(); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + if (IsValidIndex(idx)) + { + // + result = bar.Init( + symbol, + period, + idx // + ); + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Check Same ... + bool IsSameAs(XDirectionShift &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid(); + if (!result) + { + return result; + } + + // + result = + // + at == item.at && + type == item.type && + after == item.after && + before == item.before && + symbol == item.symbol && + period == item.period && + shiftTo == item.shiftTo + // + ; + + // + return result; + } +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/Libraries/x-saherelm.x-trade.lib.mq5 b/BKPS/14040626/Libraries/x-saherelm.x-trade.lib.mq5 new file mode 100644 index 0000000..fe62281 --- /dev/null +++ b/BKPS/14040626/Libraries/x-saherelm.x-trade.lib.mq5 @@ -0,0 +1,6464 @@ +/////////////////////////////////////////////////////// +// +// 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 "../Libraries/x-saherelm.x-guard.lib.mq5" +#include + +// +// Definitions ... + +// +// a List of Used Tokens ... + +// +// Common ... +string XIDToken = "ID"; +string XTicketToken = "TK"; +string XModeToken = "MD"; +string XTypeToken = "TY"; +string XPeriodToken = "PR"; +string XProviderToken = "PRV"; +string XProfitToken = "PF"; + +// +string XTPToken = "TP"; +string XSLToken = "SL"; +string XTimeToken = "TM"; +string XEntryToken = "EN"; +string XVolumeToken = "VL"; +string XSymbolToken = "SMBL"; + +// +string XSupportToken = "SP"; +string XEQMSupportToken = "EQM"; +string XEQPToken = "EQP"; + +// +string XSLTrailToken = "SLT"; + +// +string XActionToken = "A"; + +// +string XDirectionalToken = "D"; +string XINDirectionalToken = "IND"; + +// +string XRecoveryToken = "XRCV"; + +// +// Available Order Modes ... +enum ENUM_X_ORDER_MODES +{ + X_ORDER_MODE_NOTHING, // Nothing + X_ORDER_MODE_MARKET, // Market Order + X_ORDER_MODE_STOP, // Pending Stop Order + X_ORDER_MODE_LIMIT, // Pending Limit Order + X_ORDER_MODE_STOP_LIMIT, // Pending Stop Limit Order +}; + +// +string ToString(ENUM_X_ORDER_MODES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_ORDER_MODE_MARKET: + result = "Market"; + break; + + // + case X_ORDER_MODE_LIMIT: + result = "Limit"; + break; + + // + case X_ORDER_MODE_STOP: + result = "Stop"; + break; + + // + case X_ORDER_MODE_STOP_LIMIT: + result = "StopLimit"; + break; + } + + // + return result; +} + +// +// Select Positions Type ... +enum ENUM_X_POSITION_SELECT_METHODS +{ + X_POSITION_SELECT_NONE, // None + X_POSITION_SELECT_MAX, // Max + X_POSITION_SELECT_MIN, // Min + X_POSITION_SELECT_BOTH, // Min and Max + X_POSITION_SELECT_ALL, // All +}; + +// +// Signal Execution Result ... +// note that some of them must be handles in +// EA's ... +enum ENUM_X_SIGNAL_EXECUTION_RESULT +{ + // + X_SIGNAL_EXECUTION_UNKNOWN, // Unknown + X_SIGNAL_EXECUTION_SUCCEED, // Succed + X_SIGNAL_EXECUTION_FAILED_SPREAD, // Spread more than Max Allowed + X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED, // Not Allowed Trade Type + X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade + X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error + X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR, // Prev Profit Error + X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached + X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED, // Same Positions Delay Not Passed + X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params +}; + +// +enum ENUM_X_POSITION_TYPES +{ + X_POSITION_TYPE_NONE = 0, + X_POSITION_TYPE_ALL = 1, + X_POSITION_TYPE_LONG = 2, + X_POSITION_TYPE_SHORT = 3, +}; + +// +bool IsValid(ENUM_X_POSITION_TYPES value) +{ + return value != X_POSITION_TYPE_NONE; +} + +// +bool HasSpecifiedType(ENUM_X_POSITION_TYPES value) +{ + // + return value == X_POSITION_TYPE_LONG || + value == X_POSITION_TYPE_SHORT; +} + +// +string ToString(ENUM_X_POSITION_TYPES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POSITION_TYPE_ALL: + result = "All"; + break; + + // + case X_POSITION_TYPE_NONE: + result = "NONE"; + break; + + // + case X_POSITION_TYPE_SHORT: + result = "Short"; + break; + + // + case X_POSITION_TYPE_LONG: + result = "Long"; + break; + } + + // + return result; +} +string ToXString(ENUM_X_POSITION_TYPES value) +{ + return ToString(value); +} + +// +bool IsLong(ENUM_X_POSITION_TYPES value) +{ + return value == X_POSITION_TYPE_LONG; +} + +// +bool IsShort(ENUM_X_POSITION_TYPES value) +{ + return value == X_POSITION_TYPE_SHORT; +} + +// +bool ToPositionType( + ENUM_POSITION_TYPE &dest, + ENUM_X_POSITION_TYPES source // +) +{ + // + bool result = false; + + // + result = source == X_POSITION_TYPE_LONG || + source == X_POSITION_TYPE_SHORT; + if (!result) + { + return result; + } + + // + dest = + source == X_POSITION_TYPE_LONG + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + return result; +} + +// +ENUM_X_POSITION_TYPES ToPositionType(ENUM_POSITION_TYPE value) +{ + return IsLong(value) + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; +} + +// +ENUM_X_POSITION_TYPES OppositPositionType(ENUM_POSITION_TYPE type) +{ + // + ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE; + + // + bool isLong = IsLong(type); + bool isShort = IsShort(type); + + // + result = + // + isLong + ? X_POSITION_TYPE_SHORT + : isShort + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_NONE + // + ; + + // + return result; +} + +// +ENUM_X_DIRECTION ToDirection(ENUM_POSITION_TYPE value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + result = IsLong(value) + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +// +ENUM_X_DIRECTION ToDirection(ENUM_X_POSITION_TYPES value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + result = value == X_POSITION_TYPE_ALL + ? X_DIRECTION_ALL + : value == X_POSITION_TYPE_LONG + ? X_DIRECTION_BULLISH + : value == X_POSITION_TYPE_SHORT + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + return result; +} + +// +// All Awailable Trade Restrictions ... +enum ENUM_XTRADE_RESTRICTION_PERIOD +{ + XTRADE_RESTRICATION_NONE, // None + XTRADE_RESTRICATION_HOURLY, // Per Hour + XTRADE_RESTRICATION_DAILY, // Per Day + XTRADE_RESTRICATION_WEEKLY, // Per Week + XTRADE_RESTRICATION_MONTHLY, // Per Month +}; + +// +string ToXString(ENUM_XTRADE_RESTRICTION_PERIOD value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +ENUM_XTRADE_RESTRICTION_PERIOD ToXRestrictionPeriod(string value) +{ + // + ENUM_XTRADE_RESTRICTION_PERIOD result = XTRADE_RESTRICATION_NONE; + + // + if (!IsSpecifiedValid(value)) + { + return result; + } + + // + // None ... + if (value == ToXString(XTRADE_RESTRICATION_NONE)) + { + result = XTRADE_RESTRICATION_NONE; + } + // + // Per Hour ... + else if (value == ToXString(XTRADE_RESTRICATION_HOURLY)) + { + result = XTRADE_RESTRICATION_HOURLY; + } + // + // Per Day ... + else if (value == ToXString(XTRADE_RESTRICATION_DAILY)) + { + result = XTRADE_RESTRICATION_DAILY; + } + // + // Per Week ... + else if (value == ToXString(XTRADE_RESTRICATION_WEEKLY)) + { + result = XTRADE_RESTRICATION_WEEKLY; + } + // + // Per Month ... + else if (value == ToXString(XTRADE_RESTRICATION_MONTHLY)) + { + result = XTRADE_RESTRICATION_MONTHLY; + } + + // + return result; +} + +// +int GetXRestrictionsPeriodSeconds(ENUM_XTRADE_RESTRICTION_PERIOD value) +{ + // + int result = 0; + + // + if (!HasRestrictions(value)) + { + return result; + } + + // + switch (value) + { + // + // None ... + case XTRADE_RESTRICATION_NONE: + result = 0; + break; + + // + // Hour ... + case XTRADE_RESTRICATION_HOURLY: + result = PeriodSeconds(PERIOD_H1); + break; + + // + // Dayly ... + case XTRADE_RESTRICATION_DAILY: + result = PeriodSeconds(PERIOD_D1); + break; + + // + // Weekly ... + case XTRADE_RESTRICATION_WEEKLY: + result = PeriodSeconds(PERIOD_W1); + break; + + // + // Monthly ... + case XTRADE_RESTRICATION_MONTHLY: + result = PeriodSeconds(PERIOD_M1); + break; + } + + // + return result; +} + +/** + * Check a Value Has Trade Restrictions or not ... + * + * @param value: ENUM_XTRADE_RESTRICTION_PERIOD + * Ù‘ + * @return ( bool ) + */ +bool HasRestrictions(ENUM_XTRADE_RESTRICTION_PERIOD value) +{ + return value != XTRADE_RESTRICATION_NONE; +} + +// +// All Awailable Trade Finalizations ... +enum ENUM_XTRADE_FINALIZATION +{ + XTRADE_FINAL_NONE, // None + XTRADE_FINAL_TP, // TP + XTRADE_FINAL_SL, // SL + XTRADE_FINAL_CLOSE_IN_PROFIT, // Profit + XTRADE_FINAL_CLOSE_IN_LOSE, // Lost +}; + +// +string ToXString(ENUM_XTRADE_FINALIZATION value) +{ + return EnumToString(value); +} + +// +// Position Selecting Methods ... +enum ENUM_XPOSITION_SELECT_TYPES +{ + XPOSITION_SELECT_NONE = 0, // None + XPOSITION_SELECT_ALL = 1, // All + XPOSITION_SELECT_IN_PROFITS = 2, // In Profit Positions + XPOSITION_SELECT_IN_DRAWDOWNS = 3, // In Drawdown Positions + XPOSITION_SELECT_OLDEST = 4, // Oldest Position + XPOSITION_SELECT_YOUNGEST = 5, // Youngest Position + XPOSITION_SELECT_IN_PROFITS_OLDEST = 6, // In Profit Positions Oldest one + XPOSITION_SELECT_IN_PROFITS_YOUNGEST = 7, // In Profit Positions Youngest one + XPOSITION_SELECT_IN_PROFITS_MIN = 8, // Minimum Profitable Position + XPOSITION_SELECT_IN_PROFITS_MAX = 9, // Maximum Profitable Position + XPOSITION_SELECT_IN_DRAWDOWN_OLDEST = 10, // In Drawdown Positions Oldest one + XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST = 11, // In Drawdown Positions Youngest one + XPOSITION_SELECT_IN_DRAWDOWN_MIN = 12, // Minimum in Drawdown Position + XPOSITION_SELECT_IN_DRAWDOWN_MAX = 13, // Maximum in Drawdown Position + XPOSITION_SELECT_SAMES = 14, // Same Type Positions + XPOSITION_SELECT_SAMES_OLDEST = 15, // Same Type Positions Oldest one + XPOSITION_SELECT_SAMES_YOUNGEST = 16, // Same Type Positions Youngest one + XPOSITION_SELECT_OPPOSITS = 17, // Opposit Type Positions + XPOSITION_SELECT_OPPOSIT_OLDEST = 18, // Opposit Type Positions Oldest one + XPOSITION_SELECT_OPPOSIT_YOUNGEST = 19, // Opposit Type Positions Youngest one + XPOSITION_SELECT_SAME_IN_PROFITS = 20, // Same Type In Profit Positions + XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST = 21, // Same Type In Profit Positions Oldest one + XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST = 22, // Same Type In Profit Positions Youngest one + XPOSITION_SELECT_SAME_IN_PROFITS_MIN = 23, // Minimum Profitable of Same Type Positions + XPOSITION_SELECT_SAME_IN_PROFITS_MAX = 24, // Maximum Profitable of Same Type Positions + XPOSITION_SELECT_OPPOSIT_IN_PROFITS = 25, // Opposit Type In Profit Positions + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST = 26, // Opposit Type In Profit Positions Oldest one + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST = 27, // Opposit Type In Profit Positions Youngest one + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN = 28, // Minimum Profitable of Opposit Type Positions + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX = 29, // Maximum Profitable of Opposit Type Positions + XPOSITION_SELECT_SAME_IN_DRAWDOWNS = 30, // Same Type In Deawdown Positions + XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST = 31, // Same Type In Deawdown Positions Oldest one + XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST = 32, // Same Type In Deawdown Positions Youngest one + XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN = 33, // Minimum In Drawdown of Same Type Positions + XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX = 34, // Maximum In Drawdown of Same Type Positions + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS = 35, // Opposit Type In Deawdown Positions + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST = 36, // Opposit Type In Deawdown Positions Oldest one + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST = 37, // Opposit Type In Deawdown Positions Youngest one + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN = 38, // Minimum In Drawdown of Opposit Type Positions + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX = 39, // Maximum In Drawdown of Opposit Type Positions +}; + +/** + * Validate Position Select Type ... + * + * @param value: ENUM_XPOSITION_SELECT_TYPES + * + * @return ( bool ) + */ +bool IsXValid(ENUM_XPOSITION_SELECT_TYPES value) +{ + return value != XPOSITION_SELECT_NONE; +} + +// +string ToXString(ENUM_XPOSITION_SELECT_TYPES value) +{ + return EnumToString(value); +} + +// +// 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; + + // + SpecifiedClean(tps); + + // + ZeroMemory(this); + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + double _sl, + double _entry, + ENUM_X_POSITION_TYPES _type, + string _prefix = NULL // + ) + { + // + bool result = false; + + // + result = + _sl > 0 && + _entry > 0 && + IsSpecifiedValid(_symbol) && + IsSpecifiedValid(_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 && + IsSpecifiedValid(time) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(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 + (IsSpecifiedValid(prefix) ? prefix + sep : "") + symbol + sep + ToXString(period) + sep + ToFormatString(time) + sep + ToString(type); + + // + return result; + } +}; + +// +// Model a Target ... +struct XTarget +{ + // + // Props ... + bool doRF; // Do RF on Target + double target; // Target Price for Actions + double volumeMultiplier; // Volume Multiplier for Partial Close + + // + // Constructor ... + XTarget() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + target = 0; + doRF = false; + volumeMultiplier = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = target > 0; + + // + return result; + } +}; + +// +// Get Lowest Target index ... +int GetLowest(XTarget &targets[]) +{ + // + int result = -1; + + // + if (!HasChild(targets)) + { + return result; + } + + // + XTarget iTarget; + int count = ArraySize(targets); + for (int i = 0; i < count; i++) + { + // + bool canSet = + !iTarget.IsValid() + ? true + : iTarget.target > targets[i].target; + if (canSet) + { + // + result = i; + iTarget = targets[i]; + } + } + + // + iTarget.Clean(); + + // + return result; +} + +// +// Get Highest Target index ... +int GetHighest(XTarget &targets[]) +{ + // + int result = -1; + + // + if (!HasChild(targets)) + { + return result; + } + + // + XTarget iTarget; + int count = ArraySize(targets); + for (int i = 0; i < count; i++) + { + // + bool canSet = + !iTarget.IsValid() + ? true + : iTarget.target < targets[i].target; + if (canSet) + { + // + result = i; + iTarget = targets[i]; + } + } + + // + iTarget.Clean(); + + // + return result; +} + +// +// Apply Sorting on Targets ... +void ApplySortOnTargets( + ENUM_X_DIRECTION forDir, // Target Sorting Direction ... + XTarget &targets[] // Targets to Apply Sorting ... +) +{ + // + bool has = HasChild(targets) && + HasDirection(forDir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + XTarget tmp[]; + Copy( + targets, + tmp // + ); + Clean(targets); + while (HasChild(tmp)) + { + // + int idx = -1; + if (isBullish) + { + idx = GetLowest(tmp); + } + else if (isBearish) + { + idx = GetHighest(tmp); + } + + // + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XTarget iTarget = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + AddRef( + iTarget, + targets // + ); + } + + // + Clean(tmp); +} + +// +// Model an Open Position ... +struct XPosition +{ + // + // Props ... + + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Sifnal Provider ... + string provider; + + // + // Position Comment ... + string comment; + + // + // Constructor ... + XPosition() + { + Clean(); + } + + // + // Initializers ... + + bool ByIndex(int index) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + ulong mTicket = mPositionInfo.Ticket(); + + // + result = ByTicket(mTicket); + + // + return result; + } + + bool ByTicket(ulong mTicket) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByTicket(mTicket); + if (!result) + { + return result; + } + + // + swap = mPositionInfo.Swap(); + magic = mPositionInfo.Magic(); + openAt = mPositionInfo.Time(); + sl = mPositionInfo.StopLoss(); + ticket = mPositionInfo.Ticket(); + symbol = mPositionInfo.Symbol(); + tp = mPositionInfo.TakeProfit(); + profit = mPositionInfo.Profit(); + volume = mPositionInfo.Volume(); + comment = mPositionInfo.Comment(); + entry = mPositionInfo.PriceOpen(); + type = mPositionInfo.PositionType(); + price = mPositionInfo.PriceCurrent(); + commission = mPositionInfo.Commission(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + magic = 0; + ticket = 0; + tp = 0; + sl = 0; + swap = 0; + entry = 0; + price = 0; + profit = 0; + volume = 0; + openAt = 0; + commission = 0; + + // + type = NULL; + period = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(symbol) && + NotEmpty(ticket) + // + ; + + // + return result; + } + + // + // Retrieve Entry Price ... + double GetEntry() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetXEntry( + symbol, + type + // + ); + + // + return result; + } + + // + // Retrieve Exit ... + double GetExit() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetXExit( + symbol, + type + // + ); + + // + return result; + } + + // + // Get Spread by Point ... + double GetSpread() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = PriceToPoint(GetXSpread(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; + } + + // + double GetRiskInPoint() + { + // + double result = 0; + + // + result = GetRisk() / GetPoints(); + + // + 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; + + // + SpecifiedClean(tps); + + // + bool isValid = IsValid(); + if (!isValid) + { + return result; + } + + // + double risk = GetRisk(); + int r2r = (int)GetRiskRewardRatio(); + bool isLong = IsLong(type); + for (int i = 0; i < r2r; i++) + { + // + double iValue = + isLong + ? entry + risk + (i * risk) + : entry - risk - (i * risk); + // + Add( + iValue, + tps // + ); + } + + // + result = ArraySize(tps); + + // + return result; + } + + // + // Calculate Reached TP Levels ... + void CalculateReahedTP( + double &reachedLevel, + double &reachedPrice // + ) + { + // + reachedLevel = -1; + reachedPrice = 0; + double tps[]; + bool isLong = IsLong(type); + double exitPrice = GetExit(); + int tpLevels = CalculateTPLevels(tps); + if (!IsValidSize(tpLevels) || exitPrice <= 0) + { + return; + } + + // + for (int i = 0; i < tpLevels - 1; i++) + { + // + double cTP = tps[i]; + double nTP = tps[i + 1]; + + // + bool isReached = + isLong + ? exitPrice > cTP && + exitPrice < nTP + : exitPrice < cTP && + exitPrice > nTP; + if (isReached) + { + // + reachedLevel = i + 1; + reachedPrice = cTP; + } + } + } + + // + // Calculate Touched Reward ... + double CalculateTouchedReward() + { + // + double result = 0.0; + + // + bool has = IsValid() && + profit > 0; + if (!has) + { + return result; + } + + // + double risk = MathAbs(entry - sl); + double currentReward = MathAbs(price - entry); + + // + result = currentReward / risk; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetXAge(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( + XPosition &values[] // Collection to Find + ) + { + // + return FindXIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell) + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Signal ... +struct XSignal +{ + // + // Props ... + + // + ulong positionId; // if Executed this filled ... + + // + datetime time; // Issue Time ... + + // + double tp; // Take Profit ... + double sl; // Stop Loss ... + double entry; // Exntry or Execution Price ... + double volume; // Position Volume ... + + // + string symbol; // Trading Symbol ... + string comment; // Comment ... + string provider; // Signaller ... + + // + ENUM_TIMEFRAMES period; // Trading TimeFrame ... + ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ... + ENUM_X_ORDER_MODES mode; // Execution Mode ... + + // + string conditions; // Signal Conditions ... + + // + // Additional ... + + // + // Traget ... + XTarget targets[]; // Provided Targets ... + int appliedTargetIDX; // Last Applied Target Index ... + bool ignoreEAVolume; // Ignore EA Volume ... + bool isTargetApplied; // Check if Target Applied or not ... + + // + // Constructor ... + XSignal() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + entry = 0; + volume = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + conditions = NULL; + + // + SpecifiedClean(targets); + appliedTargetIDX = -1; + ignoreEAVolume = false; + isTargetApplied = false; + + // + ZeroMemory(this); + } + + // + // Default Values ... + void Default() + { + // + entry = 0; + volume = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + conditions = NULL; + + // + SpecifiedClean(targets); + appliedTargetIDX = -1; + ignoreEAVolume = false; + isTargetApplied = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(period) && + IsSpecifiedValid(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 (IsSpecifiedValid(provider)) + { + // + // Generate Provider Tag ... + result += GenerateProviderTag(provider); + } + + // + if (IsSpecifiedValid(period)) + { + // + // Generate Period Tag ... + result += GeneratePeriodTag(period); + } + + // + return result; + } + + // + int GetAge() + { + // + return GetXAge( + this, + this.period // + ); + } + + // + // Find Risk ... + double GetRisk() + { + // + double result = 0; + + // + if (!IsValid()) + { + return 0; + } + + // + result = MathAbs(entry - sl); + + // + return result; + } + + // + // Find Reward ... + double GetReward() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathAbs(tp - entry); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + result = "XSignal_" + + symbol + "_" + + ToXString(period) + "_" + + ToXString(type) + "_" + + ToXString(sl) + "_" + + ToXString(tp) + "_" + + ToXString(entry); + + // + return result; + } + + // + // Retrieve String Representation of Signal ... + string ToString() + { + // + string result = NULL; + + // + result = + // + ToXString("Symbol", symbol) + + ToXString("Period", period) + + ToXString("Provider", provider) + + ToXString("Type", type) + + ToXString("Mode", mode) + + ToXString("Volume", volume) + + ToXString("Entry", entry) + + ToXString("TP", tp) + + ToXString("SL", sl) + + ToXString("Time", time) + + ToXString("Comment", comment) + + // + "" + // + ; + + // + return result; + } + + // + bool IsSameAs(XSignal &item) + { + // + bool result = false; + + // + result = + // + IsValid() && + item.IsValid() && + // + tp == item.tp && + sl == item.sl && + mode == item.mode && + time == item.time && + type == item.type && + entry == item.entry && + symbol == item.symbol && + period == item.period && + provider == item.provider + // + ; + + // + return result; + } + + // + string GetMessage(string action = NULL) + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = ToXString(type) + + " Signal" + + (!IsSpecifiedValid(action) + ? "" + : " " + action) + + " by: " + provider + + " on (" + symbol + ")" + + " in: " + ToXString(period); + + // + return result; + } + + // + string GetFileName() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + symbol + "\\" + + ToXString(type) + "\\" + + ToXString(period) + "_" + + ToFormatString(time) + // + ; + + // + return result; + } +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long positionId; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string symbol; + + // + // Signal Provider ... + string provider; + + // + // Order Comment ... + string comment; + + // + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOrder() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static COrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Retrieve Specific History Order ... + bool HistoryByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static CHistoryOrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + tp = 0; + sl = 0; + magic = 0; + ticket = 0; + positionId = 0; + openPrice = 0; + currentPrice = 0; + initialVolume = 0; + currentVolume = 0; + stopLimitPrice = 0; + + // + setupAt = NULL; + expiredAt = NULL; + executedAt = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + state = NULL; + period = NULL; + filling = NULL; + lifetime = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetXAge(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( + XOrder &values[] // Collection to Find + ) + { + // + return FindXIndex( + 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 = + // + IsSpecifiedValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetXAge(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( + XDeal &values[] // Collection to Find + ) + { + // + return FindXIndex( + 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; + } +}; + +// +// an Structure for Describe aTrading Session ... +struct XTradeSession +{ + // + // Properties ... + string start; // Session Start Time (hh:mm) + string end; // Session End Time (hh:mm) + string name; // Session Name + + // + // Constructor ... + XTradeSession() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + end = NULL; + name = NULL; + start = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(start) && + IsSpecifiedValid(end); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Check Session is Active or Not ... + bool IsActive(datetime time = NULL) + { + // + bool result = false; + + // + time = NormalizeTime(time); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsTimeInRange( + time, + start, + end // + ); + + // + return result; + } +}; + +// +// an Structure for Describe an Specified Symbols +// Trading Sessions ... +struct XSymbolTradeConfig +{ + // + // Propeties ... + + // + int longs; // All Long Trades + int shorts; // All Short Trades + int trades; // All Trades + int losses; // All Loosing Trades + int profits; // All Winning Trades + string symbol; // Trading Symbol + int managedSLs; // Managed SL(s) + int managedTPs; // Managed TP(s) + int managedTrades; // Managed Trades + int maxAllowedTPs; // Max Allowed TP(s) in Restrictions Period + int maxAllowedSLs; // Max Allowed SL(s) in Restrictions Period + int maxAllowedTrades; // Max Allowed Trades in Restrictions Period + datetime managedStart; // Managed Start Time + double managedBalance; // Managed Start Balance + double managedProfits; // Managed Profit(s) + ENUM_TIMEFRAMES period; // Trading Period + int maxAllowedPositions; // Max Allowed Same Time Trades + double maxAllowedSpread; // Max Allowed Spread For Trade + bool isForceCloseAtTime; // a Flag for Determines Force Closed or not + XTradeSession sessions[]; // Trading Sessions + string closeAllOpenTradesAt; // Close All Open Trades per Day At Specified Time + int restrictionsPeriodMultiplier; // Specified Restrictions Period Multiplier + ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; // Trade Restrictions Period + + // + // Constructor ... + XSymbolTradeConfig() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + period = NULL; + SpecifiedClean(sessions); + + // + longs = 0; + shorts = 0; + trades = 0; + losses = 0; + profits = 0; + + // + managedStart = NULL; + + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + + // + managedBalance = 0; + managedProfits = 0; + + // + maxAllowedTPs = 0; + maxAllowedSLs = 0; + maxAllowedTrades = 0; + maxAllowedSpread = 25; + maxAllowedPositions = 5; + closeAllOpenTradesAt = ""; + isForceCloseAtTime = false; + restrictionsPeriod = XTRADE_RESTRICATION_NONE; + + // + ZeroMemory(this); + } + + /** + * Initial ... + * + * @param _symbol: Trading Symbol + * @param _period: Trading Period + * @param _sessionsDescriptor: Sessions Description + * @param _maxAllowedSpread: Max Allowed Spread for Open Trade + * @param _maxAllowedPositions: Max Allowed Same Time Position + * @param _restrictionsDescriptor: Restrictions Descriptor + * + * @return ( bool ) + */ + bool Init( + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL, + string _sessionsDescriptor = NULL, + double _maxAllowedSpread = 25, + int _maxAllowedPositions = 5, + string _restrictionsDescriptor = NULL // + ) + { + // + bool result = false; + + // + // Normalize Symbol ... + _symbol = NormalizeSymbol(_symbol); + _period = NormalizePeriod(_period); + + // + symbol = _symbol; + period = _period; + maxAllowedSpread = _maxAllowedSpread; + maxAllowedPositions = _maxAllowedPositions; + + // + // Parse Sessions ... + ParseSessions(_sessionsDescriptor); + + // + // Parse Restrictions ... + ParseRestrictions(_restrictionsDescriptor); + + // + // Check Validation ... + result = IsValid(); + + // + return result; + } + + // + // Check Same ... + bool IsSame(XSymbolTradeConfig &dest) + { + // + bool result = false; + + // + // Validate ... + result = IsValid() && + dest.IsValid() && + symbol == dest.symbol && + period == dest.period; + + // + return result; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period); + + // + return result; + } + + // + // Check Allow Trade in Active Sessions ... + bool CanTrade(datetime time = NULL) + { + // + bool result = false; + + // + // Normalize Args ... + time = NormalizeTime(time); + + // + // Validating ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // if there is not any defined sessions for Symbol ... + // it's allow Trading in all times ... + result = !HasChild(sessions); + if (result) + { + return result; + } + + // + // Detect an Active Session ... + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].IsActive(time); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Checking Restrictions ... + bool IsRestricted(datetime time = NULL) + { + // + bool result = false; + + // + // Normalize Time ... + time = NormalizeTime(time); + + // + // Check Has Restrictions ... + bool has = HasRestrictions(restrictionsPeriod); + result = !has; + if (result) + { + return result; + } + + // + // Check Restrictions Time ... + has = IsSpecifiedValid(managedStart) && + time <= managedStart; + result = !has; + if (result) + { + return result; + } + + // + // Validate Restrictions Timing ... + // Check Restrictions ... + + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + if (result) + { + return result; + } + + // + // Check Restrictions Reset ... + HandleRestrictions(); + + // + return result; + } + + // + // Parse Sessions ... + void ParseSessions(string descriptor) + { + // + // Validate ... + if (!IsSpecifiedValid(descriptor)) + { + return; + } + + // + bool has = false; + string _sessions[]; + int sessionsCount = 0; + + // + // Extract Per Symbol Sessions ... + sessionsCount = SplitContent( + _sessions, + descriptor, + "," // + ); + + // + // Try to Extract Start and End Times Series ... + has = IsValidSize(sessionsCount); + if (!has) + { + return; + } + + // + // Iterate Sessions ... + for (int i = 0; i < sessionsCount; i++) + { + // + // Ignore unused Cases and Extracts only Content ... + string iSessionDescriptorStr = ExtractString(_sessions[i]); + has = IsSpecifiedValid(iSessionDescriptorStr); + if (has) + { + // + // Extract Session Descriptor Data ... + string parts[]; + int partsCount = SplitContent( + parts, + iSessionDescriptorStr, + "_" // + ); + has = IsValidSize(partsCount) && partsCount == 3; + if (has) + { + // + string iName = parts[0]; + string iStart = parts[1]; + string iEnd = parts[2]; + has = IsSpecifiedValid(iName) && + IsSpecifiedValid(iStart) && + IsSpecifiedValid(iEnd); + if (has) + { + // + // Set Active Session Per Symbols ... + XTradeSession session; + + // + session.end = iEnd; + session.name = iName; + session.start = iStart; + + // + AddRef( + session, + sessions // + ); + + // + session.Clean(); + } + } + + // + SpecifiedClean(parts); + } + } + + // + SpecifiedClean(_sessions); + } + + // + // Parse Restrictions ... + void ParseRestrictions(string descriptor) + { + // + // Validate ... + if (!IsSpecifiedValid(descriptor)) + { + return; + } + + // + // Extract Content ... + descriptor = ExtractString(descriptor); + if (!IsSpecifiedValid(descriptor)) + { + return; + } + + // + int count = 0; + bool has = false; + string iRestrictionsParts[]; + + // + // Extract Parts ... + count = SplitContent( + iRestrictionsParts, + descriptor, + "," // + ); + has = IsValidSize(count); + if (!has) + { + // + // Default Restrictions ... + ApplyDefaultRestrictions(); + return; + } + + // + // Try To Extract Required Parts ... + bool hasRestrictionsPeriod = count >= 1; + bool hasRestrictionsPeriodMultiplier = count >= 2; + bool hasMaxAllowedTPs = count >= 3; + bool hasMaxAllowedSLs = count >= 4; + bool hasMaxAllowedTrades = count >= 5; + bool hasCloseAllOpenTradesAt = count >= 6; + + // + // Restrictions Period ... + restrictionsPeriod = + hasRestrictionsPeriod + ? ToXRestrictionPeriod(Trim(iRestrictionsParts[0])) + : XTRADE_RESTRICATION_NONE; + + // + // Restrictions Period Multiplier ... + restrictionsPeriodMultiplier = + hasRestrictionsPeriodMultiplier + ? (int)(Trim(iRestrictionsParts[1])) + : 1; + + // + // Max Allowed TPs ... + maxAllowedTPs = + hasMaxAllowedTPs + ? (int)(Trim(iRestrictionsParts[2])) + : 0; + + // + // Max Allowed SLs ... + maxAllowedSLs = + hasMaxAllowedSLs + ? (int)(Trim(iRestrictionsParts[3])) + : 0; + + // + // Max Allowed Trades ... + maxAllowedTrades = + hasMaxAllowedTrades + ? (int)(Trim(iRestrictionsParts[4])) + : 0; + + // + // Close All Open Trades At ... + closeAllOpenTradesAt = + hasCloseAllOpenTradesAt + ? Trim(iRestrictionsParts[5]) + : NULL; + } + + // + // Apply Default Restrictions ... + void ApplyDefaultRestrictions() + { + // + maxAllowedTPs = 0; + maxAllowedSLs = 0; + maxAllowedTrades = 0; + closeAllOpenTradesAt = NULL; + restrictionsPeriod = XTRADE_RESTRICATION_NONE; + } + + // + // Handle Restrictions ... + void HandleRestrictions(datetime time = NULL) + { + // + // Normalize Time ... + time = NormalizeTime(time); + + // + // Check Restrictions Requirements ... + bool has = HasRestrictions(restrictionsPeriod) && + restrictionsPeriodMultiplier >= 1; + if (!has) + { + return; + } + + // + // Check Restrictions Start ... + has = IsSpecifiedValid(managedStart); + if (!has) + { + managedStart = time; + } + + // + // Calculating Expiration Date based on Config ... + int expiredDelay = restrictionsPeriodMultiplier * GetXRestrictionsPeriodSeconds(restrictionsPeriod); + datetime expiredDate = (datetime)(TimeToSeconds(managedStart) + expiredDelay); + + // + // Check Expiration ... + has = time >= expiredDate; + if (!has) + { + return; + } + + // + ResetRestrictions(); + } + + // + // Reset Restrictions ... + void ResetRestrictions() + { + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + managedBalance = 0; + managedProfits = 0; + managedStart = TimeCurrent(); + } + + // +}; + +// +// an Structure to Describe a Trade ... +struct XTradeInfo +{ + // + // Props ... + double swap; + double profit; + XSignal signal; + ulong positionID; + double commission; + string conditions; + double bullishScore; + double bearishScore; + ENUM_XTRADE_FINALIZATION finalize; + + // + datetime signaledAt; + datetime executedAt; + datetime finalizedAt; + + // + // Constructor ... + XTradeInfo() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swap = 0; + profit = 0; + signal.Clean(); + commission = 0; + positionID = 0; + conditions = NULL; + bullishScore = 0; + bearishScore = 0; + finalize = XTRADE_FINAL_NONE; + + // + signaledAt = NULL; + executedAt = NULL; + finalizedAt = NULL; + + // + ZeroMemory(this); + } + + /** + * Check Has Signal ... + * + * @return ( bool ) + */ + bool HasSignal() + { + // + bool result = false; + + // + result = signal.IsValid(); + + // + return result; + } + + /** + * Check Signal Executed or Not ... + * + * @return ( bool ) + */ + bool IsExecuted() + { + // + bool result = false; + + // + result = positionID > 0; + + // + return result; + } + + /** + * Check a Trade is Finalized or not ... + * + * @return ( bool ) + */ + bool IsFinalized() + { + // + bool result = false; + + // + result = HasSignal() && + IsExecuted() && + finalize != XTRADE_FINAL_NONE; + + // + return result; + } + + /** + * Generate Summary Info ... + * + * @return ( string ) + */ + string Summary() + { + // + string result = NULL; + + // + result = + // + ToXString("Swap", swap) + + ToXString("Profit", profit) + + ToXString("Commission", commission) + + ToXString("Finalize", ToXString(finalize)) + + ToXString("PositionID", positionID) + + ToXString("----------------") + "\n" + + ToXString("Signaled At", ToFormatString(signaledAt)) + + ToXString("Executed At", ToFormatString(executedAt)) + + ToXString("Finalized At", ToFormatString(finalizedAt)) + // + ; + + // + return result; + } + + /** + * Get Data Collection File Name ... + * + * @return ( string ) + */ + string GetFileName() + { + // + string result = NULL; + + // + bool hasSignal = HasSignal(); + bool isExecuted = IsExecuted(); + bool isFinalized = IsFinalized(); + if (!hasSignal && !isExecuted && !isFinalized) + { + return result; + } + + // + result = + // + signal.symbol + "\\" + + ToString(signal.type) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(positionID) + "_" + + ToString(signal.period) + "_" + + ToFormatString(signaledAt) + // + ; + + // + return result; + } + + /** + * Converts Model to String Representation ... + * + * @param onlySignals: Boolean, Specified Represent Only Signal or not ... + * + * @return ( string ) + */ + string ToString( + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + string result = NULL; + + // + // Generating Model Summary ... + string summary = Summary(); + + // + // Generating Signal Summary ... + string signalSummary = signal.ToString(); + + // + if (includeSummary) + { + // + result += + ToXString("----------------") + "\n" + + ToXString("Summary: ") + "\n" + + ToXString("----------------") + "\n" + + summary + "\n"; + } + + // + if (includeSignal) + { + // + result += + ToXString("----------------") + "\n" + + ToXString("Signal: ") + "\n" + + ToXString("----------------") + "\n" + + signalSummary + "\n"; + } + + // + if (includeConditions) + { + // + result += + ToXString("----------------") + "\n" + + ToXString("Conditions: ") + "\n" + + ToXString("----------------") + "\n" + + conditions + "\n"; + } + + // + return result; + } + + string GetConditionsString() + { + // + string result = NULL; + + // + string conditionsStr = + conditions; + string condParts[]; + int condPartsCount = SplitContent( + condParts, + conditionsStr, + "\n" // + ); + if (IsValidSize(condPartsCount)) + { + // + conditionsStr = NULL; + while (HasChild(condParts)) + { + // + string iStr = condParts[0]; + ArrayRemove( + condParts, + 0, + 1 // + ); + + // + bool isLast = !HasChild(condParts); + + // + bool isCond = Contains( + "is", + iStr, + false // + ); + if (isCond) + { + // + string iParts[]; + int iPartsCount = SplitContent( + iParts, + iStr, + ":" // + ); + if (iPartsCount == 2) + { + // + string iVal = iParts[1]; + StringTrimLeft(iVal); + StringTrimRight(iVal); + bool isPassed = ToBoolean(iVal); + conditionsStr += (isPassed ? "" : "!") + "conditions." + iParts[0] + (!isLast ? " &&" : "") + "\n"; + } + } + } + SpecifiedClean(condParts); + } + else + { + conditionsStr = NULL; + } + + // + result = + "(" + "\n" + + "\\" + "\\" + " " + ToXString("Type", ToXString(signal.type)) + + "\\" + "\\" + " " + ToXString("Profit", profit) + + "\\" + "\\" + " " + ToXString("Finalize", ToXString(finalize)) + + "\\" + "\\" + " " + ToXString("PositionID", positionID) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + "\\" + "\\" + " " + ToXString("Signaled At", ToFormatString(signaledAt)) + + "\\" + "\\" + " " + ToXString("Executed At", ToFormatString(executedAt)) + + "\\" + "\\" + " " + ToXString("Finalized At", ToFormatString(finalizedAt)) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + "\\" + "\\" + " " + ToXString("Scores:") + "\n" + + "\\" + "\\" + " " + ToXString("Bullish", bullishScore) + + "\\" + "\\" + " " + ToXString("Bearish", bearishScore) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + conditionsStr + + (IsValid(conditionsStr) ? "" : "") + + ") && "; + + // + return result; + } +}; + +// +// TypeDefs ... + +// +typedef void (*TOnSignal)(XSignal &signal); + +// +typedef bool (*TCanAnalyse)( + string _symbol, + ENUM_TIMEFRAMES _period, + datetime _time // +); + +// +// an Event Type for Notify Guard Triggered ... +typedef void (*TOnGuarded)( + ENUM_X_GUARD_ACTIONS guard, + XPosition &positions[]); + +// +typedef int (*TCheckForGuard)(XGuard &guards[]); + +// +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; +} +int GetXAge( + XSignal &signal, // Selected Signal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + return GetAge(signal, period); +} + +// +// 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; +} +int GetXAge( + XPosition &position, // Selected Position ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + return GetAge(position, period); +} + +// +// 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; +} +int GetXAge( + XOrder &order, // Selected Order ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + return GetAge(order, period); +} + +// +// 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; +} +int GetXAge( + XDeal &deal, // Selected Deal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + return GetAge(deal, period); +} + +// +// 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; +} +int GetXOldest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + return GetOldest(item, items); +} + +// +// 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; +} +int GetXYoungest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + return GetYoungest(item, items); +} + +// +// 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; +} +int GetXOldest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + return GetOldest(item, items); +} + +// +// 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; +} +int GetXYoungest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + return GetYoungest(item, items); +} + +// +// 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; +} +int GetXOldest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + return GetOldest(item, items); +} + +// +// 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 GetXYoungest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + return GetYoungest(item, items); +} + +// +int FindMaxProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (max == 0 || + max < iPosition.profit) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int FindMinProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInProfitPositions( + XPosition &positions[], // Position Collection + XPosition &inProfits[] // Result +) +{ + // + int result = 0; + + // + Clean(inProfits); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + inProfits // + ); + } + } + + // + result = ArraySize(inProfits); + + // + return result; +} + +// +int FindMaxDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (max == 0 || + MathAbs(max) < MathAbs(iPosition.profit)) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int FindMinDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInDrawdownPositions( + XPosition &positions[], // Position Collection + XPosition &inDradowns[] // Result +) +{ + // + int result = 0; + + // + Clean(inDradowns); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + inDradowns // + ); + } + } + + // + result = ArraySize(inDradowns); + + // + return result; +} + +// +// Check Filters ... + +// +// Magic Filter ... +template +bool IsMagicFilterPassed( + ulong magic, + bool filterByMagic, + T &item + // +) +{ + // + return !filterByMagic + ? true + : !NotEmpty(magic) + ? false + : magic == item.magic; +} + +// +// Symbol Filter ... +template +bool IsSymbolFilterPassed( + string symbol, + T &item + // +) +{ + // + return !IsValid(symbol) + ? true + : symbol == item.symbol; +} + +// +// Provider Filter ... +template +bool IsProviderFilterPassed( + string provider, + T &item + // +) +{ + // + return !IsValid(provider) + ? true + : provider == item.provider; +} + +// +// Period Filter ... +template +bool IsPeriodFilterPassed( + ENUM_TIMEFRAMES period, + T &item + // +) +{ + // + return !IsValid(period) + ? true + : period == item.period; +} + +// +// Type Filter ... +template +bool IsTypeFilterPassed( + ENUM_POSITION_TYPE type, + T &item + // +) +{ + // + bool result = type == item.type; + + // + return result; +} +template +bool IsTypeFilterPassed( + ENUM_X_POSITION_TYPES type, + T &item + // +) +{ + // + bool result = type == NULL || type == X_POSITION_TYPE_ALL + ? true + : ((type == X_POSITION_TYPE_LONG && ((int)item.type == (int)POSITION_TYPE_BUY || (int)item.type == (int)ORDER_TYPE_BUY)) || + (type == X_POSITION_TYPE_SHORT && ((int)item.type == (int)POSITION_TYPE_SELL || (int)item.type == (int)ORDER_TYPE_SELL))); + + // + return result; +} +template +bool IsTypeFilterPassed( + ENUM_ORDER_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} +template +bool IsTypeFilterPassed( + ENUM_DEAL_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} + +// +// Mode Filter ... +template +bool IsModeFilterPassed( + ENUM_X_ORDER_MODES mode, + T &item + // +) +{ + // + return mode == NULL + ? true + : mode == item.mode; +} + +// +// Entry Filter ... +template +bool IsEntryFilterPassed( + ENUM_DEAL_ENTRY entry, + T &item + // +) +{ + // + return entry == NULL + ? true + : entry == item.entry; +} + +// +// Reason Filter ... +template +bool IsReasonFilterPassed( + ENUM_DEAL_REASON reason, + T &item + // +) +{ + // + return reason == NULL + ? true + : reason == item.reason; +} + +// +// State Filter ... +template +bool IsStateFilterPassed( + ENUM_ORDER_STATE state, + T &item + // +) +{ + // + return state == NULL + ? true + : state == item.state; +} + +// + +// +// +// Calculate Positions Profit Summary ... +double SpecifiedCalculatePositionsProfit( + XPosition &positions[] // Source +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + result += iPosition.profit; + } + + // + return result; +} + +// +// Calculate Required Profit for Hedging ... +double SpecifiedCalculateRequiredProfitForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; + if (!isHedgingEnable) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) + { + // + result += + ((iPosition.volume / mMinProfitPerVolumeFactor) * + mMinProfitPerTrade) + + (-1 * iPosition.swap); + } + } + + // + return result; +} + +// +bool SpecifiedIsPositionsReadyForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + bool result = requiredProfit > 0 + ? profit >= requiredProfit + : profit > requiredProfit; + + // + return result; +} + +// +int FindCoverageDrawdownPosition( + XPosition &position, // In Drawdown Position + XPosition &inProfits[], // In Profit Positions + XPosition &coverage[], // Coverage Positons + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + Clean(coverage); + + // + if (!position.IsValid() || position.profit >= 0) + { + return result; + } + + // + int inProfitsCount = ArraySize(inProfits); + if (!IsValidSize(inProfitsCount)) + { + return result; + } + + // + // Copy in Profits to TMP ... + XPosition tmp[]; + Copy( + inProfits, + tmp // + ); + + // + bool isCoverPassed = false; + while (!isCoverPassed || ArraySize(tmp) > 0) + { + // + XPosition max; + int idx = FindMaxProfitIndex(tmp); + if (idx >= 0) + { + // + if (tmp[idx].profit > 0) + { + AddRef( + tmp[idx], + coverage // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + + // + // Check Cover Passed ... + XPosition tmpPositions[]; + Copy( + coverage, + tmpPositions // + ); + AddRef( + position, + tmpPositions // + ); + + // + double profits = SpecifiedCalculatePositionsProfit(tmpPositions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + tmpPositions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + isCoverPassed = profits >= requiredProfit; + if (isCoverPassed) + { + break; + } + + // + if (!isCoverPassed && ArraySize(tmp) == 0) + { + break; + } + } + + // + result = ArraySize(coverage); + + // + return result; +} + +// +// Extract a Collection of Positions SL ... +int ExtractSLs( + XPosition &positions[], + double &sls[] // +) +{ + // + int result = 0; + + // + Clean(sls); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.sl > 0) + { + // + Add( + iPosition.sl, + sls // + ); + } + } + + // + result = ArraySize(sls); + + // + return result; +} + +// +// Extract a Colletion of Positions TP ... +int ExtractTPs( + XPosition &positions[], + double &tps[] // +) +{ + // + int result = 0; + + // + Clean(tps); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.tp > 0) + { + // + Add( + iPosition.tp, + tps // + ); + } + } + + // + result = ArraySize(tps); + + // + return result; +} + +// +// Retrieve String Representation ... +string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SIGNAL_EXECUTION_UNKNOWN: + result = "Unknown"; + break; + + // + case X_SIGNAL_EXECUTION_SUCCEED: + result = "Succed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_SPREAD: + result = "Spread more than Max Allowed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED: + result = "not Allowed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_NO_EQUITY: + result = "No Equity for Trade"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR: + result = "Price Error"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR: + result = "Previous Position Profit not Passed for Accept Next"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: + result = "Max Allowed Positions Reached"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED: + result = "Min Delay Between to Signal not Passed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS: + result = "Invalid Params"; + break; + } + + // + return result; +} + +// +// Converts Position Type to Order Type ... +ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value) +{ + // + bool isLong = IsLong(value); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} +ENUM_ORDER_TYPE ToOrderType(ENUM_X_POSITION_TYPES value) +{ + // + ENUM_POSITION_TYPE mType = + value == X_POSITION_TYPE_SHORT + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + bool isLong = IsLong(mType); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} + +// +// Tagging ... + +// +// Generate Specified Tag for Using in Comments ... +string GeneratePeriodTag(ENUM_TIMEFRAMES period) +{ + // + string strPeriod = ToXString(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 // + ); + } + } +} + +// +// Apply a Collection of Targets +// on Specified Signal ... +void ApplyTargetsOnSignal( + ENUM_X_DIRECTION sortingDir, // Target Sorting Direction ... + XTarget &targets[], // Required Targets ... + XSignal &signal // Destination Signal ... +) +{ + // + bool has = + HasChild(targets) && + HasDirection(sortingDir); + if (!has) + { + return; + } + + // + // Sort Targets ... + ApplySortOnTargets( + sortingDir, + targets // + ); + + // + Copy( + targets, + signal.targets // + ); +} + +/** + * Select Specified Position's Related Position(s) + * for Protecting ... + * + * @param selecteds: XPosition instance reference Collection, for Holding Selected Positions ... + * @param positions: XPosition instance reference Collection, All available source Positions ... + * @param forType: ENUM_X_POSITION_TYPES member, Spcified Position Type to Select for it ... + * @param selectType: ENUM_XPOSITION_SELECT_TYPES member, Specified Positions Selecting Senario ... + * + * @return ( bool ) + */ +bool SelectPosition( + XPosition &selecteds[], + XPosition &positions[], + ENUM_X_POSITION_TYPES forType, + ENUM_XPOSITION_SELECT_TYPES selectType // +) +{ + // + bool result = false; + + // + // Normalize Args ... + Clean(selecteds); + + // + // Validate Args ... + result = + IsValid(forType) && + HasChild(positions) && + IsXValid(selectType); + if (!result) + { + return result; + } + + // + // Extract Separate Type of Positions ... + + // + int idx = -1; + bool has = false; + XPosition iPosition; + + // + bool isLong = IsLong(forType); + bool isShort = IsShort(forType); + int count = ArraySize(positions); + + // + XPosition samePositions[]; + XPosition oppositPositions[]; + XPosition inProfitPositions[]; + XPosition inDrawdownPositions[]; + XPosition sameInProfitPositions[]; + XPosition sameInDrawdownPositions[]; + XPosition oppositInProfitPositions[]; + XPosition oppositInDrawdownPositions[]; + + // + for (int i = 0; i < count; i++) + { + // + // Select Indexed Position ... + iPosition = positions[i]; + + // + bool isIPosLong = IsLong(iPosition.type); + bool isIPosShort = IsShort(iPosition.type); + + // + // Select if Same Type ... + bool isSame = + (isLong && isIPosLong) || + (isShort && isIPosShort); + if (isSame) + { + // + AddRef( + iPosition, + samePositions // + ); + } + + // + // Select if Opposit Type ... + bool isOpposit = + (isLong && isIPosShort) || + (isShort && isIPosLong); + if (isOpposit) + { + // + AddRef( + iPosition, + oppositPositions // + ); + } + + // + iPosition.Clean(); + } + + // + // Filling Other Requirement Collections ... + + // + ExtractInProfitPositions( + positions, + inProfitPositions // + ); + + // + ExtractInProfitPositions( + samePositions, + sameInProfitPositions // + ); + + // + ExtractInProfitPositions( + oppositPositions, + oppositInProfitPositions // + ); + + // + ExtractInDrawdownPositions( + positions, + inDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + samePositions, + sameInDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + oppositPositions, + oppositInDrawdownPositions // + ); + + // + // Implement Selection Senario ... + switch (selectType) + { + // + case XPOSITION_SELECT_ALL: + // + Copy( + positions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_IN_PROFITS: + // + Copy( + inProfitPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWNS: + // + Copy( + inDrawdownPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OLDEST: + // + GetOldest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_YOUNGEST: + // + GetYoungest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAMES: + // + Copy( + samePositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_SAMES_OLDEST: + // + GetOldest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAMES_YOUNGEST: + // + GetYoungest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS: + // + Copy( + oppositPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OPPOSIT_OLDEST: + // + GetOldest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_YOUNGEST: + // + GetYoungest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS: + // + Copy( + sameInProfitPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS: + // + Copy( + oppositInProfitPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWNS: + // + Copy( + sameInDrawdownPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS: + // + Copy( + oppositInDrawdownPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + } + + // + // Validate Result ... + result = HasChild(selecteds); + + // + // Cleanup Resources ... + + // + if (!result) + { + Clean(selecteds); + } + + // + Clean(samePositions); + Clean(oppositPositions); + Clean(inProfitPositions); + Clean(inDrawdownPositions); + Clean(sameInProfitPositions); + Clean(sameInDrawdownPositions); + Clean(oppositInProfitPositions); + Clean(oppositInDrawdownPositions); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/XCATBEA/Classes/xcatbea.expert.class.mq5 b/BKPS/14040626/XCATBEA/Classes/xcatbea.expert.class.mq5 new file mode 100644 index 0000000..81fae78 --- /dev/null +++ b/BKPS/14040626/XCATBEA/Classes/xcatbea.expert.class.mq5 @@ -0,0 +1,3376 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCATBEAExpert ... +// Description: XCATB Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCATB Expert Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-guard.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" +#include "../../Classes/x-saherelm.x-volume.class.mq5" +#include "../Classes/xcatbea.signaller.class.mq5" +#include "../Classes/xcatbea.x-trade.manager.class.mq5" + +// +// Definitions ... +#define XCATBEA_INPUTS_PREFIX "X121XCATBEA" + +// +// Implementation ... + +// +class XCXCATBEASignallerInputParser : public XCBase +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + XCXCATBEASignallerInputParser( + XCAlert *_alert // + ) + { + // + alert = _alert; + + // + // Instantiate Data Collector ... + collector = new XCDataCollector(); + + // + // Generate Path and Attached to Data Collector ... + // string mPath = alert.GetPrefix(); + collector.Path(""); + } + + // + // Deconstructor ... + ~XCXCATBEASignallerInputParser() + { + // + delete collector; + ZeroMemory(collector); + } + + // + // Tools and Actions ... + + /** + * Retrieve Specified Symbol / Period Signaller Inputs ... + * + * @param symbol: string, Specified Signaller Symbol ... + * @param period: ENUM_TIMEFRAMES member, Specified Signaller Period ... + * + * @return ( bool ) + */ + string GetFileName( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + string result = NULL; + + // + // Validate Args ... + if (!IsValid(symbol) || + !IsValid(period)) + { + return result; + } + + // + result = XCATBEA_INPUTS_PREFIX + "_" + symbol + "_" + ToXString(period); + result = collector.GetFilePath(result); + + // + return result; + } + + /** + * Check Specified Symbol / Period Signaller Inputs File Exists ... + * + * @param symbol: string, Specified Signaller Symbol ... + * @param period: ENUM_TIMEFRAMES member, Specified Signaller Period ... + * + * @return ( bool ) + */ + bool IsSignallerInputsFileExists( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + bool result = false; + + // + string fileName = GetFileName( + symbol, + period // + ); + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + result = collector.IsExists(fileName); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Parse Specified Symbol / Period Signaller Inputs file ... + * + * @param inputs: XCATBEASignallerInputs instance reference, To Fill Loaded Configs ... + * @param symbol: string, Specified Signaller Symbol ... + * @param period: ENUM_TIMEFRAMES member, Specified Signaller Period ... + * + * @return ( bool ) + */ + bool ParseSignallerInputs( + XCATBEASignallerInputs &inputs, + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + inputs.symbol = symbol; + inputs.period = period; + + // + // Prepare File Name and Check File Exists ... + string fileName = GetFileName(symbol, period); + result = collector.IsExists(fileName); + if (!result) + { + return result; + } + + // + // Read Content ... + string content[]; + result = collector.Read(fileName, content); + if (!result) + { + return result; + } + + // + // Try to Parse Content ... + result = HasChild(content); + if (result) + { + // + int count = ArraySize(content); + for (int i = 0; i < count; i++) + { + // + string iLine = content[i]; + + // + Parse(iLine, inputs); + } + } + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + XCAlert *alert; + XCDataCollector *collector; + + /** + * Parse Condition and Attached to related Properties if Exists ... + */ + void Parse( + string line, + XCATBEASignallerInputs &inputs // + ) + { + // + string parts[]; + bool has = false; + int partsCount = 0; + + // + // Validations ... + + // + // eaForceHasSwing ... + has = Contains( + "eaForceHasSwing", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceHasSwing = has; + } + } + } + + // + // eaForceOBBarType ... + has = Contains( + "eaForceOBBarType", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceOBBarType = has; + } + } + } + + // + // eaForceFVGBarType ... + has = Contains( + "eaForceFVGBarType", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceFVGBarType = has; + } + } + } + + // + // eaForceHasFLiquidity ... + has = Contains( + "eaForceHasFLiquidity", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceHasFLiquidity = has; + } + } + } + + // + // eaForceHasRLiquidity ... + has = Contains( + "eaForceHasRLiquidity", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceHasRLiquidity = has; + } + } + } + + // + // eaValidateGapSequence ... + has = Contains( + "eaValidateGapSequence", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.validateGapSequence = has; + } + } + } + + // + // eaValidateBlockEdgeBreakout ... + has = Contains( + "eaValidateBlockEdgeBreakout", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.validateBlockEdgeBreakout = has; + } + } + } + + // + // Filters ... + + // + // eaFilterBasedOnKI ... + has = Contains( + "eaFilterBasedOnKI", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnKI = has; + } + } + } + + // + // eaFilterBasedOnPV ... + has = Contains( + "eaFilterBasedOnPV", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnPV = has; + } + } + } + + // + // eaFilterBasedOnSar ... + has = Contains( + "eaFilterBasedOnSar", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnSar = has; + } + } + } + + // + // eaForceSarSwitched ... + has = Contains( + "eaForceSarSwitched", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarSwitched = has; + } + } + } + + // + // eaForceSarOnBothSide ... + has = Contains( + "eaForceSarOnBothSide", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarOnBothSide = has; + } + } + } + + // + // eaForceSarHasBreakout ... + has = Contains( + "eaForceSarHasBreakout", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarHasBreakout = has; + } + } + } + + // + // eaForceSarHasReversalSide ... + has = Contains( + "eaForceSarHasReversalSide", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarHasReversalSide = has; + } + } + } + + // + // eaFilterBasedOnRSI ... + has = Contains( + "eaFilterBasedOnRSI", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnRSI = has; + } + } + } + + // + // eaForceHasRSITrending ... + has = Contains( + "eaForceHasRSITrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasRSITrending = has; + } + } + } + + // + // eaForceHasRSIVPattern ... + has = Contains( + "eaForceHasRSIVPattern", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasRSIVPattern = has; + } + } + } + + // + // eaForceHasRSICrossing ... + has = Contains( + "eaForceHasRSICrossing", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasRSICrossing = has; + } + } + } + + // + // eaFilterBasedOnADX ... + has = Contains( + "eaFilterBasedOnADX", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnADX = has; + } + } + } + + // + // eaForceHasADXTrending ... + has = Contains( + "eaForceHasADXTrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasADXTrending = has; + } + } + } + + // + // eaForceHasADXCrossing ... + has = Contains( + "eaForceHasADXCrossing", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasADXCrossing = has; + } + } + } + + // + // eaFilterBasedOnATR ... + has = Contains( + "eaFilterBasedOnATR", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnATR = has; + } + } + } + + // + // eaForceHasATRTrending ... + has = Contains( + "eaForceHasATRTrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasATRTrending = has; + } + } + } + + // + // eaForceHasATRBreakout ... + has = Contains( + "eaForceHasATRBreakout", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasATRBreakout = has; + } + } + } + + // + // eaFilterBasedOnTrend ... + has = Contains( + "eaFilterBasedOnTrend", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnTrend = has; + } + } + } + + // + // eaForceHasTrendDir ... + has = Contains( + "eaForceHasTrendDir", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendDir = has; + } + } + } + + // + // eaForceHasTrendPlace ... + has = Contains( + "eaForceHasTrendPlace", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendPlace = has; + } + } + } + + // + // eaForceHasTrendChange ... + has = Contains( + "eaForceHasTrendChange", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendChange = has; + } + } + } + + // + // eaForceHasTrendTrending ... + has = Contains( + "eaForceHasTrendTrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendTrending = has; + } + } + } + + // + // eaForceHasTrendRejection ... + has = Contains( + "eaForceHasTrendRejection", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendRejection = has; + } + } + } + + // + // eaForceHasTrendLineInside ... + has = Contains( + "eaForceHasTrendLineInside", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendLineInside = has; + } + } + } + + // + // eaForceHasTrendDirOnBothSide ... + has = Contains( + "eaForceHasTrendDirOnBothSide", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendDirOnBothSide = has; + } + } + } + + // + // eaFilterBasedOnDelta ... + has = Contains( + "eaFilterBasedOnDelta", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnDelta = has; + } + } + } + + // + // eaFilterBasedOnVolume ... + has = Contains( + "eaFilterBasedOnVolume", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnVolume = has; + } + } + } + + // + // eaFilterBasedOnSignalBar ... + has = Contains( + "eaFilterBasedOnSignalBar", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnSignalBar = has; + } + } + } + + // + // eaFilterBasedOnHKSignalBar ... + has = Contains( + "eaFilterBasedOnHKSignalBar", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnHKSignalBar = has; + } + } + } + + // + } + + // +}; + +// +class XCXCATBEAExpert : public XCBase +{ + // + // public ... + public: + // + // Props ... + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Detector ... + + // + // Validating ... + bool eaForceHasSwing; // Force Block to Has Propper Swing + bool eaForceOBBarType; // Force Order Block to Has InDirectional Bars + int eaMinRequiredOBBar; // Min Required OB Bar + bool eaForceFVGBarType; // Force Fair Value Gaps Bars Type + int eaLiquidityLoopback; // Liquidity Detection Loopback + double eaMaxAllowedRange; // Max Allowed Order Block Range + double eaMinAllowedRange; // Min Allowed Order Block Range + bool eaForceHasFLiquidity; // Force Order Block To Has Reversal Liquidity + bool eaForceHasRLiquidity; // Force Order Block to Has Following Liquidity + bool eaValidateGapSequence; // Validate Fair Value Gaps Bar Sequences + int eaMinAllowedBlockLength; // Min Allowed Block Length + bool eaValidateBlockEdgeBreakout; // Validate Order Block Edge Breakeout + + // + // Filtering ... + bool eaFilterBasedOnKI; // Filter Based On KI Flats + bool eaFilterBasedOnPV; // Filter Based On PV + int eaBosLoopback; // PV Based Filtering BOS Lookup + bool eaFilterBasedOnSar; // Filter Based On SAR + bool eaForceSarSwitched; // SAR Switched on Sides for Filtering + bool eaForceSarOnBothSide; // SAR Check on Both Sides for Filtering + bool eaForceSarHasBreakout; // SAR Must Breakout + bool eaForceSarHasReversalSide; // SAR Must Has Reversal Direction + bool eaFilterBasedOnRSI; // Filter Based On RSI + bool eaForceHasRSITrending; // RSI Must Has Trending + bool eaForceHasRSIVPattern; // RSI Must Has Pattern + bool eaForceHasRSICrossing; // RSI Must Has Crossing Levels + bool eaFilterBasedOnADX; // Filter Based On ADX + bool eaForceHasADXTrending; // ADX Must Has Trending + bool eaForceHasADXCrossing; // ADX Must Has Crossing +DI/-DI + bool eaFilterBasedOnATR; // Filter Based On ATR + bool eaForceHasATRTrending; // ATR Must Has Trending + bool eaForceHasATRBreakout; // ATR Must Has Breakout + bool eaFilterBasedOnTrend; // Filter Based On Trend + bool eaForceHasTrendDir; // TREND Must Has Following Direction + bool eaForceHasTrendPlace; // TREND Place Based Filtering + bool eaForceHasTrendChange; // TREND Change Filtering + bool eaForceHasTrendTrending; // TREND Must Has Trending + bool eaForceHasTrendRejection; // TREND Line Must Rejected + bool eaForceHasTrendLineInside; // TREND Line has Inside + bool eaForceHasTrendDirOnBothSide; // TREND Must Has Following Direction in Both Side + bool eaFilterBasedOnDelta; // Filter Based On Delta + bool eaFilterBasedOnVolume; // Filter Based On Volume + bool eaFilterBasedOnSignalBar; // Filter Based on Signal Bar + bool eaFilterBasedOnHKSignalBar; // Filter Based On HK Signal Bar + + // + // Signal ... + int eaSignalR2R; // Risk Reward Ratio + double eaSLATRMultiplier; // ATR Multiplier for SL + bool eaAllowSignallingBasedOnConditions; // Signalling Based on Market Conditions + bool eaAllowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks + bool eaAllowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs + bool eaSecondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss + bool eaApplyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss + bool eaAllowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool eaAllowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool eaAllowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool eaAllowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool eaAllowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool eaAllowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + + // + // Volume ... + ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type + double eaStaticVoluem; // Static Volume + double eaDynamicVolumeStepBalance; // Step of Balance for Increase Volume + double eaDynamicVolumeStepVolume; // Step of Volume Increasing + double eaConstantRiskBalance; // Constant Risk Balance per Trade + double eaConstantPercent; // Constant Percent of Balance Per Trade + double eaConstantBalance; // Constant Balance for Calculations + + // + // Management ... + string eaSymbols; // Allowed Trading Symbols + bool eaAllowGuards; // Allow Guards + bool eaAllowTrade; // Allow Trade on Signals + bool eaAllowLongs; // Allow Long Trades + bool eaAllowShorts; // Allow Short Trades + string eaSessions; // Active Sessions + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod; // Restrictions Period + int eaMaxAllowedTPs; // Max Allowed TP(s) in Restrictions Period + int eaMaxAllowedSLs; // Max Allowed SL(s) in Restrictions Period + int eaMaxAllowedTrades; // Max Allowed Trades in Restrictions Period + int eaMaxAllowedPositions; // Max Allowed Same Time Trades + double eaMaxAllowedSpread; // Max Allowed Spread For Trade + double eaMaxAllowedDrawdownFactor; // Max Allowed DrawDown for Trade + string eaCloseAllOpenTradesAt; // Close All Open Trades per Day At Specified Time + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // Time Report ... + bool eaReportNewMonths; // Report New Month + bool eaReportNewWeeks; // Report New Weeks + bool eaReportNewDays; // Report New Days + bool eaReportNewHours; // Report New Hours + bool eaReportTrades; // Report Trades + bool eaReportSignals; // Report Signals + bool eaReportProtector; // Report Protector Actions + bool eaReportRestrictions; // Report Restrictions + bool eaReportAfterTradesBalance; // Report Balance after a Trade Finished + + // + // Collector ... + bool eaSaveTrades; // Save Trades + bool eaSaveSignals; // Save Signals + bool eaSaveWins; // Save Winning Conditions + bool eaSaveLosts; // Save Lost Conditions + bool eaSaveRestrictions; // Save Restriction Reports + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCTrade *eaTrade; // EA Scope Trade Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + XCDataCollector *eaCollector; // EA Scope Data Collector ... + XCXCATBEASignaller *eaSignallers[]; // EA Signallers Collection ... + XCXCATBEATradeManager *eaTradeManager; // EA Scope Trade Manager ... + XCXCATBEASignallerInputParser *eaSignallerInputParser; // EA Scope Signaller Input Parser ... + + // + // Tools / Actions / Handlers ... + + // + // Trade Event Handlers ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // Implement all Inputs Validation ... + result = eaMagicNumber > 0 && + eaSignalR2R > 0; + + // + return result; + } + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + bool has = false; + int count = -1; + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetSaveAlerts(eaSaveAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Volume Manager ... + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Initialize Trader ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + + // + // Trade Handler Attachments ... + + // + // Position Modifiy Event Handlers ... + count = ArraySize(mOnModifyEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); + } + } + + // + // Position Stop Loss Event Handlers ... + if (has) + { + // + count = ArraySize(mStopLossEventHandlers); + has = IsValidSize(count); + for (int i = 0; i < count; i++) + { + eaTrade.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); + } + } + + // + // Position Take Profit Event Handlers ... + count = ArraySize(mTakeProfitEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); + } + } + + // + // Position Force Close Event Handlers ... + count = ArraySize(mOnForceCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); + } + } + + // + // Deals Changed Event Handlers ... + count = ArraySize(mDealsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); + } + } + + // + // Orders Changed Event Handlers ... + count = ArraySize(mOrdersChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); + } + } + + // + // Positions Changed Event Handlers ... + count = ArraySize(mPositionsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); + } + } + // + // Trade Changed Event Handlers ... + count = ArraySize(mTradeStateChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); + } + } + // + // Postion Partially Close Event Handlers ... + count = ArraySize(mOnPartialCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); + } + } + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrade // + ); + + // + // Initialize Data Collector ... + eaCollector = new XCDataCollector(); + string mPath = eaAlert.GetPrefix() + "\\" + "Configs"; + eaCollector.Path(mPath); + + // + // Instantiating Signaller Input Parser ... + eaSignallerInputParser = new XCXCATBEASignallerInputParser(eaAlert); + + // + // Initialize Trae Manager ... + eaTradeManager = new XCXCATBEATradeManager( + eaAlert, + eaTrade // + ); + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Enable Force Close At ... + eaTradeManager.SetForceCloseTradesAt(eaCloseAllOpenTradesAt); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Trade Restrictions ... + eaTradeManager + .SetTradeRestrictions( + eaRestrictionsPeriod, + eaMaxAllowedTPs, + eaMaxAllowedSLs, + eaMaxAllowedTrades // + ); + + // + // Parsing Symbols ... + + // + string symbols[]; + int symbolsCount = 0; + if (IsValid(eaSymbols)) + { + // + symbolsCount = SplitContent( + symbols, + eaSymbols, + "," // + ); + } + + // + // Adding Default Symbol, if eaSymbols not Filled ... + if (!HasChild(symbols)) + { + // + Add( + _Symbol, + symbols // + ); + + // + symbolsCount = ArraySize(symbols); + } + bool hasSymbols = HasChild(symbols); + + // + // Initializing Sessions ... + string sessions[]; + int sessionsCount = 0; + bool hasSession = IsValid(eaSessions); + if (hasSession) + { + // + // Extract Per Symbol Sessions ... + sessionsCount = SplitContent( + sessions, + eaSessions, + "," // + ); + + // + // Try to Extract Start and End Times Series ... + hasSession = IsValidSize(sessionsCount); + if (hasSession) + { + // + // Iterate Sessions ... + for (int i = 0; i < sessionsCount; i++) + { + // + // Ignore unused Cases and Extracts only Content ... + string iSessionDescriptorStr = ExtractString(sessions[i]); + bool isInited = IsValid(iSessionDescriptorStr); + if (isInited) + { + // + // Extract Session Descriptor Data ... + string parts[]; + int partsCount = SplitContent( + parts, + iSessionDescriptorStr, + "_" // + ); + isInited = IsValidSize(partsCount) && partsCount == 3; + if (isInited) + { + // + string iName = parts[0]; + string iStart = parts[1]; + string iEnd = parts[2]; + isInited = IsValid(iName) && + IsValid(iStart) && + IsValid(iEnd); + if (isInited) + { + // + // Set Active Session Per Symbols ... + if (hasSymbols) + { + // + for (int j = 0; j < symbolsCount; j++) + { + // + eaTradeManager + .SetTradeSession( + symbols[j], + iStart, + iEnd, + iName // + ); + } + } + } + } + } + } + } + } + + // + // Initialize Signallers ... + if (hasSymbols) + { + // + // Prepare Signaller Inputs ... + XCATBEASignallerInputs iSignallerInputs; + + // + // Common Configs ... + + // + // Provider Name ... + iSignallerInputs.period = _Period; + iSignallerInputs.allowDraws = false; + iSignallerInputs.provider = "XTRGB"; + iSignallerInputs.allowGuards = eaAllowGuards; + iSignallerInputs.riskToRewardRatio = eaSignalR2R; + iSignallerInputs.slATRMultiplier = eaSLATRMultiplier; + + // + // CATB Indicator ... + iSignallerInputs.catbInputs.Default(); + iSignallerInputs.catbInputs.Hide(); + + // + // Make Available all Requirement Buffers of XCATB indicator ... + iSignallerInputs.catbInputs.showPV = true; + iSignallerInputs.catbInputs.showKI = true; + iSignallerInputs.catbInputs.showSar = true; + iSignallerInputs.catbInputs.showTrend = true; + iSignallerInputs.catbInputs.showATRBand = true; + iSignallerInputs.catbInputs.showPVGolden = true; + + // + // Signalling Configurations ... + iSignallerInputs.signallerConfigs.allowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + iSignallerInputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + iSignallerInputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + iSignallerInputs.signallerConfigs.allowSignallingConditions1 = eaAllowSignallingConditions1; + iSignallerInputs.signallerConfigs.allowSignallingConditions2 = eaAllowSignallingConditions2; + iSignallerInputs.signallerConfigs.allowSignallingConditions3 = eaAllowSignallingConditions3; + iSignallerInputs.signallerConfigs.allowSignallingConditions4 = eaAllowSignallingConditions4; + iSignallerInputs.signallerConfigs.allowSignallingConditions5 = eaAllowSignallingConditions5; + iSignallerInputs.signallerConfigs.allowSignallingConditions6 = eaAllowSignallingConditions6; + // + // Prepare Trigger Block Validations ... + + // + iSignallerInputs.validations.forceHasSwing = eaForceHasSwing; + iSignallerInputs.validations.forceOBBarType = eaForceOBBarType; + iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar; + iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType; + iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback; + iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange; + iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange; + iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity; + iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity; + iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence; + iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength; + iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Prepare Trigger Block Filters ... + + // + iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV; + iSignallerInputs.filters.bosLoopback = eaBosLoopback; + + // + iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar; + iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched; + iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide; + iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout; + iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide; + + // + iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI; + iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending; + iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern; + iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing; + + // + iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX; + iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending; + iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing; + + // + iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR; + iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending; + iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout; + + // + iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend; + iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir; + iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace; + iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange; + iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending; + iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection; + iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside; + iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + iSignallerInputs.filters.filterBasedOnKI = eaFilterBasedOnKI; + iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta; + iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume; + iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar; + iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + + // + // Loop through Symbols and Initialize Signaller + // for it, then Attached it to eaSignallers ... + for (int i = 0; i < symbolsCount; i++) + { + // + // Attach Symbol ... + iSignallerInputs.symbol = symbols[i]; + + // + // Check if Provided Inputs File Exists ... + // if Exists, Load and Parse it ... + // LoadConfig(iSignallerInputs); + + // + // Set Specified Configurations Per Symbols ... + // Based on Repack 1 ... + AssignRepack1Configs(iSignallerInputs); + + // + // Check Inputs Validation ... + if (iSignallerInputs.IsValid()) + { + // + // Initialize Signaller ... + XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs); + + // + // Add it to the Signallers List ... + Add( + iSignaller, + eaSignallers // + ); + + // + ZeroMemory(iSignaller); + } + } + + // + // Cleanup Resources ... + iSignallerInputs.Clean(); + } + + // + // since atleast one Signaller must + // exists to Expert works ... + // we check it as Last Step ... + result = hasSymbols && + HasChild(eaSignallers); + if (result) + { + // + string message = "Initialized Successfully ..."; + eaAlert.SendAlert(message); + + // + SaveConfigs(); + } + else + { + // + string message = "Initialization Failed ..."; + eaAlert.SendAlert(message); + } + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + eaTimeTracker.Clean(); + + // + Clean(eaSignallers); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + delete eaCollector; + ZeroMemory(eaCollector); + + // + delete eaSignallerInputParser; + ZeroMemory(eaSignallerInputParser); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + // + // Time Report Handling ... + HandleTimeReport(); + + // + // Position Management / Protections Handling ... + eaTradeManager.Manage(); + + // + // Check Signallers Registered ... + bool has = HasChild(eaSignallers); + if (!has) + { + return; + } + + // + // Define Collection of Requirements ... + XGuard guards[]; + XCATBEAStrategyConditions conditions[]; + + // + // Loop through Registered Signallers to Proccess Ticks and + // Collect: + // - Guards; + // - Triggered Conditions; + // - ... + int count = ArraySize(eaSignallers); + for (int i = 0; i < count; i++) + { + // + // Retrieve indexed Signaller ... + XCXCATBEASignaller *iSignaller = eaSignallers[i]; + + // + string iSymbol = iSignaller.GetSymbol(); + string iProvider = iSignaller.GetProvider(); + ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod(); + + // + // Now we Have to Check Handle Tick Resoult ... + + // + // Requirements ... + XGuard iGuards[]; // Hold Provided Guards ... + XPosition iPositions[]; // Retrieve Signaller Positions ... + XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ... + + // + // Check Active Session ... + bool isActiveSession = eaTradeManager.IsActiveSession(iSymbol); + + // + // Reading Signaller Positions ... + eaTradeManager.GetPositions( + iPositions, + iSymbol, + iProvider, + iPeriod // + ); + + // + // Processing Tick for Signaller ... + iSignaller.ProcessTick( + iPositions, + iGuards, + iConditions, + isActiveSession // + ); + + // + // Check Results ... + has = HasChild(iGuards); + if (has) + { + // + Copy( + iGuards, + guards, + false // Force Clean ... + ); + } + + // + // Check Triggered Conditions ... + has = iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + AddRef( + iConditions, + conditions // + ); + } + + // + // Cleanup Resources ... + Clean(iGuards); + Clean(iPositions); + iConditions.Clean(); + } + + // + // Do Actions Based on Provided Info ... + + // + // Guards ... + has = HasChild(guards); + if (has) + { + // + // Handle Guards Firing ... + eaGuard.DoGuards(guards); + } + + // + // Triggers ... + has = HasChild(conditions); + if (has) + { + // + // Handle Conditions Triggering ... + TriggerConditions(conditions); + } + + // + // Cleanup Resources ... + + // + Clean(guards); + Clean(conditions); + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + eaTrade.HandleOnTrade(); + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + eaTradeManager.HandleSL(deal); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + eaTradeManager.HandleTP(deal); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + eaTradeManager.HandleForceClose(position); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + eaTradeManager.HandlePartiallyClosed( + ticket, + profit, + comment // + ); + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // protected ... + protected: + // + + /** + * Report Time Changes based on Given Configurations ... + */ + void HandleTimeReport() + { + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } + } + + /** + * Update Signal Targets ... + */ + void UpdateSignalTargets(XSignal &signal) + { + // + bool has = signal.IsValid(); + if (!has) + { + return; + } + + // + // Clean Signal Targets ... + Clean(signal.targets); + + // + // Calculate Requirements ... + double r2r = eaSignalR2R > 0 + ? eaSignalR2R + : 1; + double risk = signal.GetRisk(); + double reward = risk * r2r; + + // + double isLong = IsLong(signal.type); + + // + // Handling Signal TP ... + signal.tp = + isLong + ? signal.entry + reward + : signal.entry - reward; + + // + // Try to Apply Money Management ... + + // + // Sort Targets ... + ENUM_X_DIRECTION sortingDir = + isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + ApplySortOnTargets( + sortingDir, + signal.targets // + ); + } + + /** + * Convert a Triggered Conditions to Signal and + * Execute it ... + */ + void TriggerConditions(XCATBEAStrategyConditions &conditions[]) + { + // + int count = 0; + bool has = false; + + // + has = HasChild(conditions); + if (!has) + { + return; + } + + // + count = ArraySize(conditions); + for (int i = 0; i < count; i++) + { + // + // Retrieve Indexed Conditions ... + XCATBEAStrategyConditions iConditions = conditions[i]; + + // + // Define Signal Structure ... + XSignal iSignal; + + // + // Check Conditions is Valid Triggered Conditions ... + has = + iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + // Preparing Signal ... + has = ToSignal( + iSignal, + iConditions // + ); + } + + // + // Validate Signal ... + has = iSignal.IsValid(); + if (has) + { + // + // Retrieve Signal Type ... + bool isLong = IsLong(iSignal.type); + + // + // Update Signal Entry ... + iSignal.entry = GetEntry( + iSignal.symbol, + iSignal.type // + ); + + // + // Update Signal Targets ... + UpdateSignalTargets(iSignal); + + // + // Handle Volume Management ... + double iVolume = eaVolume.CalculateVolume(iSignal); + has = iVolume > X_MIN_VOLUME && + iVolume != iSignal.volume; + if (has) + { + iSignal.volume = iVolume; + } + + // + // Execute Signal ... + has = eaTradeManager.Execute( + iSignal, + iConditions // + ); + } + + // + // Cleanup Resources ... + + // + iSignal.Clean(); + iConditions.Clean(); + } + } + + // + // private ... + private: + // + + // + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + void SaveConfigs() + { + // + string content = NULL; + + // + string separator = "\n"; + bool ignoreFalseConditions = false; + + // + // Preparng Condtions ... + content += + // + "-----------------------" + separator + + "Validating: " + separator + + "-----------------------" + separator + + ToXString("eaForceHasSwing", eaForceHasSwing, ignoreFalseConditions, separator) + + ToXString("eaForceOBBarType", eaForceOBBarType, ignoreFalseConditions, separator) + + ToXString("eaForceFVGBarType", eaForceFVGBarType, ignoreFalseConditions, separator) + + ToXString("eaForceHasFLiquidity", eaForceHasFLiquidity, ignoreFalseConditions, separator) + + ToXString("eaForceHasRLiquidity", eaForceHasRLiquidity, ignoreFalseConditions, separator) + + ToXString("eaValidateGapSequence", eaValidateGapSequence, ignoreFalseConditions, separator) + + ToXString("eaValidateBlockEdgeBreakout", eaValidateBlockEdgeBreakout, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Filtering: " + separator + + "-----------------------" + separator + + ToXString("eaFilterBasedOnKI", eaFilterBasedOnKI, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnPV", eaFilterBasedOnPV, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnSar", eaFilterBasedOnSar, ignoreFalseConditions, separator) + + ToXString("eaForceSarSwitched", eaForceSarSwitched, ignoreFalseConditions, separator) + + ToXString("eaForceSarOnBothSide", eaForceSarOnBothSide, ignoreFalseConditions, separator) + + ToXString("eaForceSarHasBreakout", eaForceSarHasBreakout, ignoreFalseConditions, separator) + + ToXString("eaForceSarHasReversalSide", eaForceSarHasReversalSide, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnRSI", eaFilterBasedOnRSI, ignoreFalseConditions, separator) + + ToXString("eaForceHasRSITrending", eaForceHasRSITrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasRSIVPattern", eaForceHasRSIVPattern, ignoreFalseConditions, separator) + + ToXString("eaForceHasRSICrossing", eaForceHasRSICrossing, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnADX", eaFilterBasedOnADX, ignoreFalseConditions, separator) + + ToXString("eaForceHasADXTrending", eaForceHasADXTrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasADXCrossing", eaForceHasADXCrossing, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnATR", eaFilterBasedOnATR, ignoreFalseConditions, separator) + + ToXString("eaForceHasATRTrending", eaForceHasATRTrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasATRBreakout", eaForceHasATRBreakout, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnTrend", eaFilterBasedOnTrend, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendDir", eaForceHasTrendDir, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendPlace", eaForceHasTrendPlace, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendChange", eaForceHasTrendChange, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendTrending", eaForceHasTrendTrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendRejection", eaForceHasTrendRejection, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendLineInside", eaForceHasTrendLineInside, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendDirOnBothSide", eaForceHasTrendDirOnBothSide, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnDelta", eaFilterBasedOnDelta, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnVolume", eaFilterBasedOnVolume, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnSignalBar", eaFilterBasedOnSignalBar, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnHKSignalBar", eaFilterBasedOnHKSignalBar, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + // Try to Save Condtions ... + string fileName = eaCollector.GetFilePath("XConfigs"); + bool has = IsValid(fileName); + if (!has) + { + return; + } + + // + eaCollector.Save( + fileName, + content // + ); + + // + // Try to Save Inputs ... + fileName = eaCollector.GetFilePath("XInputs"); + has = IsValid(fileName); + if (!has) + { + return; + } + + // + // Preparing Inputs String Reperesentation ... + content = NULL; + content += + // + "//" + separator + + "// Common ..." + separator + + ToXString("eaMagicNumber", eaMagicNumber, separator) + + ToXString("eaSlippage", eaSlippage, separator) + + ToXString("eaLogSuffix", eaLogSuffix, separator) + + "" + separator + + "//" + separator + + "// Detector ..." + separator + + "" + separator + + "//" + separator + + "// Validating ..." + separator + + ToXString("eaForceHasSwing", eaForceHasSwing, ignoreFalseConditions, separator) + + ToXString("eaForceOBBarType", eaForceOBBarType, ignoreFalseConditions, separator) + + ToXString("eaMinRequiredOBBar", eaMinRequiredOBBar, ignoreFalseConditions, separator) + + ToXString("eaForceFVGBarType", eaForceFVGBarType, ignoreFalseConditions, separator) + + ToXString("eaLiquidityLoopback", eaLiquidityLoopback, ignoreFalseConditions, separator) + + ToXString("eaMaxAllowedRange", ToXString(eaMaxAllowedRange), separator) + + ToXString("eaMinAllowedRange", ToXString(eaMinAllowedRange), separator) + + ToXString("eaForceHasFLiquidity", eaForceHasFLiquidity, ignoreFalseConditions, separator) + + ToXString("eaForceHasRLiquidity", eaForceHasRLiquidity, ignoreFalseConditions, separator) + + ToXString("eaValidateGapSequence", eaValidateGapSequence, ignoreFalseConditions, separator) + + ToXString("eaMinAllowedBlockLength", eaMinAllowedBlockLength, ignoreFalseConditions, separator) + + ToXString("eaValidateBlockEdgeBreakout", eaValidateBlockEdgeBreakout, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Filtering ..." + separator + + ToXString("eaFilterBasedOnKI", eaFilterBasedOnKI, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnPV", eaFilterBasedOnPV, ignoreFalseConditions, separator) + + ToXString("eaBosLoopback", eaBosLoopback, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnSar", eaFilterBasedOnSar, ignoreFalseConditions, separator) + + ToXString("eaForceSarSwitched", eaForceSarSwitched, ignoreFalseConditions, separator) + + ToXString("eaForceSarOnBothSide", eaForceSarOnBothSide, ignoreFalseConditions, separator) + + ToXString("eaForceSarHasBreakout", eaForceSarHasBreakout, ignoreFalseConditions, separator) + + ToXString("eaForceSarHasReversalSide", eaForceSarHasReversalSide, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnRSI", eaFilterBasedOnRSI, ignoreFalseConditions, separator) + + ToXString("eaForceHasRSITrending", eaForceHasRSITrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasRSIVPattern", eaForceHasRSIVPattern, ignoreFalseConditions, separator) + + ToXString("eaForceHasRSICrossing", eaForceHasRSICrossing, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnADX", eaFilterBasedOnADX, ignoreFalseConditions, separator) + + ToXString("eaForceHasADXTrending", eaForceHasADXTrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasADXCrossing", eaForceHasADXCrossing, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnATR", eaFilterBasedOnATR, ignoreFalseConditions, separator) + + ToXString("eaForceHasATRTrending", eaForceHasATRTrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasATRBreakout", eaForceHasATRBreakout, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnTrend", eaFilterBasedOnTrend, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendDir", eaForceHasTrendDir, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendPlace", eaForceHasTrendPlace, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendChange", eaForceHasTrendChange, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendTrending", eaForceHasTrendTrending, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendRejection", eaForceHasTrendRejection, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendLineInside", eaForceHasTrendLineInside, ignoreFalseConditions, separator) + + ToXString("eaForceHasTrendDirOnBothSide", eaForceHasTrendDirOnBothSide, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnDelta", eaFilterBasedOnDelta, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnVolume", eaFilterBasedOnVolume, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnSignalBar", eaFilterBasedOnSignalBar, ignoreFalseConditions, separator) + + ToXString("eaFilterBasedOnHKSignalBar", eaFilterBasedOnHKSignalBar, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Signal ..." + separator + + ToXString("eaSignalR2R", eaSignalR2R, ignoreFalseConditions, separator) + + ToXString("eaSLATRMultiplier", ToXString(eaSLATRMultiplier), separator) + + ToXString("eaAllowSignallingBasedOnConditions", eaAllowSignallingBasedOnConditions, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingBasedOnTriggerBlocks", eaAllowSignallingBasedOnTriggerBlocks, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingBasedOnTriggerBlocksInsideOther", eaAllowSignallingBasedOnTriggerBlocksInsideOther, ignoreFalseConditions, separator) + + ToXString("eaSecondsTriggersSLUsingFirstTriggerBlock", eaSecondsTriggersSLUsingFirstTriggerBlock, ignoreFalseConditions, separator) + + ToXString("eaApplyValidateAndFilterOnSelectInsideOthers", eaApplyValidateAndFilterOnSelectInsideOthers, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingConditions1", eaAllowSignallingConditions1, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingConditions2", eaAllowSignallingConditions2, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingConditions3", eaAllowSignallingConditions3, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingConditions4", eaAllowSignallingConditions4, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingConditions5", eaAllowSignallingConditions5, ignoreFalseConditions, separator) + + ToXString("eaAllowSignallingConditions6", eaAllowSignallingConditions6, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Volume ..." + separator + + ToXString("eaVolumeSelect", ToXString(eaVolumeSelect), separator) + + ToXString("eaStaticVoluem", ToXString(eaStaticVoluem), separator) + + ToXString("eaDynamicVolumeStepBalance", ToXString(eaDynamicVolumeStepBalance), separator) + + ToXString("eaDynamicVolumeStepVolume", ToXString(eaDynamicVolumeStepVolume), separator) + + ToXString("eaConstantRiskBalance", ToXString(eaConstantRiskBalance), separator) + + ToXString("eaConstantPercent", ToXString(eaConstantPercent), separator) + + ToXString("eaConstantBalance", ToXString(eaConstantBalance), separator) + + "" + separator + + "//" + separator + + "// Management ..." + separator + + ToXString("eaSymbols", eaSymbols, separator) + + ToXString("eaAllowGuards", eaAllowGuards, ignoreFalseConditions, separator) + + ToXString("eaAllowTrade", eaAllowTrade, ignoreFalseConditions, separator) + + ToXString("eaAllowLongs", eaAllowLongs, ignoreFalseConditions, separator) + + ToXString("eaAllowShorts", eaAllowShorts, ignoreFalseConditions, separator) + + ToXString("eaSessions", eaSessions, separator) + + ToXString("eaRestrictionsPeriod", ToXString(eaRestrictionsPeriod), separator) + + ToXString("eaMaxAllowedTPs", eaMaxAllowedTPs, ignoreFalseConditions, separator) + + ToXString("eaMaxAllowedSLs", eaMaxAllowedSLs, ignoreFalseConditions, separator) + + ToXString("eaMaxAllowedTrades", eaMaxAllowedTrades, ignoreFalseConditions, separator) + + ToXString("eaMaxAllowedPositions", eaMaxAllowedPositions, ignoreFalseConditions, separator) + + ToXString("eaMaxAllowedSpread", ToXString(eaMaxAllowedSpread), separator) + + ToXString("eaMaxAllowedDrawdownFactor", ToXString(eaMaxAllowedDrawdownFactor), separator) + + ToXString("eaCloseAllOpenTradesAt", eaCloseAllOpenTradesAt, separator) + + "" + separator + + "//" + separator + + "// Alert ..." + separator + + ToXString("eaEnableAlerts", eaEnableAlerts, ignoreFalseConditions, separator) + + ToXString("eaSaveAlerts", eaSaveAlerts, ignoreFalseConditions, separator) + + ToXString("eaLogAlerts", eaLogAlerts, ignoreFalseConditions, separator) + + ToXString("eaMailAlerts", eaMailAlerts, ignoreFalseConditions, separator) + + ToXString("eaPushAlerts", eaPushAlerts, ignoreFalseConditions, separator) + + ToXString("eaTerminalAlerts", eaTerminalAlerts, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Time Report ..." + separator + + ToXString("eaReportNewMonths", eaReportNewMonths, ignoreFalseConditions, separator) + + ToXString("eaReportNewWeeks", eaReportNewWeeks, ignoreFalseConditions, separator) + + ToXString("eaReportNewDays", eaReportNewDays, ignoreFalseConditions, separator) + + ToXString("eaReportNewHours", eaReportNewHours, ignoreFalseConditions, separator) + + ToXString("eaReportTrades", eaReportTrades, ignoreFalseConditions, separator) + + ToXString("eaReportSignals", eaReportSignals, ignoreFalseConditions, separator) + + ToXString("eaReportProtector", eaReportProtector, ignoreFalseConditions, separator) + + ToXString("eaReportRestrictions", eaReportRestrictions, ignoreFalseConditions, separator) + + ToXString("eaReportAfterTradesBalance", eaReportAfterTradesBalance, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Collector ..." + separator + + ToXString("eaSaveTrades", eaSaveTrades, ignoreFalseConditions, separator) + + ToXString("eaSaveSignals", eaSaveSignals, ignoreFalseConditions, separator) + + ToXString("eaSaveWins", eaSaveWins, ignoreFalseConditions, separator) + + ToXString("eaSaveLosts", eaSaveLosts, ignoreFalseConditions, separator) + + ToXString("eaSaveRestrictions", eaSaveRestrictions, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + eaCollector.Save( + fileName, + content // + ); + } + + // + bool LoadConfig(XCATBEASignallerInputs &inputs) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsValid(inputs.period) && + IsValid(inputs.symbol); + if (!result) + { + return result; + } + + // + // Check the Provided File Exists or not ... + result = + eaSignallerInputParser + .IsSignallerInputsFileExists( + inputs.symbol, + inputs.period // + ); + if (!result) + { + return result; + } + + // + // Parse File Content ... + result = + eaSignallerInputParser + .ParseSignallerInputs( + inputs, + inputs.symbol, + inputs.period // + ); + + // + return result; + } + + // + bool AssignRepack1Configs(XCATBEASignallerInputs &inputs) + { + // + // Validate Requirements ... + bool result = + IsValid(inputs.period) && + IsValid(inputs.symbol); + if (!result) + { + return result; + } + + // + if (inputs.symbol == "XAUUSDb") + { + // + // Validators ... + inputs.validations.forceHasSwing = false; + inputs.validations.forceOBBarType = false; + inputs.validations.forceFVGBarType = true; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = true; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = true; + inputs.filters.filterBasedOnPV = true; + inputs.filters.filterBasedOnSar = true; + inputs.filters.forceSarSwitched = false; + inputs.filters.forceSarOnBothSide = true; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = false; + inputs.filters.forceHasRSITrending = true; + inputs.filters.forceHasRSIVPattern = true; + inputs.filters.forceHasRSICrossing = false; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = true; + inputs.filters.forceHasADXCrossing = true; + inputs.filters.filterBasedOnATR = false; + inputs.filters.forceHasATRTrending = true; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = true; + inputs.filters.forceHasTrendDir = true; + inputs.filters.forceHasTrendPlace = true; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = true; + inputs.filters.forceHasTrendRejection = false; + inputs.filters.forceHasTrendLineInside = false; + inputs.filters.forceHasTrendDirOnBothSide = false; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = false; + inputs.filters.filterBasedOnSignalBar = false; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "XAGUSDb") + { + // + // Validators ... + inputs.validations.forceHasSwing = false; + inputs.validations.forceOBBarType = true; + inputs.validations.forceFVGBarType = true; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = true; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = false; + inputs.filters.filterBasedOnPV = false; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = true; + inputs.filters.forceSarOnBothSide = false; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = false; + inputs.filters.forceHasRSITrending = false; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = true; + inputs.filters.filterBasedOnADX = true; + inputs.filters.forceHasADXTrending = true; + inputs.filters.forceHasADXCrossing = true; + inputs.filters.filterBasedOnATR = false; + inputs.filters.forceHasATRTrending = true; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = false; + inputs.filters.forceHasTrendDir = true; + inputs.filters.forceHasTrendPlace = false; + inputs.filters.forceHasTrendChange = false; + inputs.filters.forceHasTrendTrending = false; + inputs.filters.forceHasTrendRejection = true; + inputs.filters.forceHasTrendLineInside = true; + inputs.filters.forceHasTrendDirOnBothSide = true; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = false; + inputs.filters.filterBasedOnSignalBar = false; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "EURUSDb") + { + // + // Validators ... + inputs.validations.forceHasSwing = false; + inputs.validations.forceOBBarType = true; + inputs.validations.forceFVGBarType = false; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = false; + inputs.validations.validateBlockEdgeBreakout = true; + + // + // Filters ... + inputs.filters.filterBasedOnKI = false; + inputs.filters.filterBasedOnPV = false; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = true; + inputs.filters.forceSarOnBothSide = false; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = true; + inputs.filters.forceHasRSITrending = true; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = false; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = true; + inputs.filters.forceHasADXCrossing = false; + inputs.filters.filterBasedOnATR = true; + inputs.filters.forceHasATRTrending = true; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = true; + inputs.filters.forceHasTrendDir = true; + inputs.filters.forceHasTrendPlace = false; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = false; + inputs.filters.forceHasTrendRejection = false; + inputs.filters.forceHasTrendLineInside = false; + inputs.filters.forceHasTrendDirOnBothSide = true; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = false; + inputs.filters.filterBasedOnSignalBar = false; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "GBPUSDb") + { + // + // Validators ... + inputs.validations.forceHasSwing = false; + inputs.validations.forceOBBarType = true; + inputs.validations.forceFVGBarType = true; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = true; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = false; + inputs.filters.filterBasedOnPV = true; + inputs.filters.filterBasedOnSar = true; + inputs.filters.forceSarSwitched = false; + inputs.filters.forceSarOnBothSide = true; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = false; + inputs.filters.filterBasedOnRSI = false; + inputs.filters.forceHasRSITrending = false; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = true; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = true; + inputs.filters.forceHasADXCrossing = false; + inputs.filters.filterBasedOnATR = false; + inputs.filters.forceHasATRTrending = false; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = false; + inputs.filters.forceHasTrendDir = true; + inputs.filters.forceHasTrendPlace = true; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = true; + inputs.filters.forceHasTrendRejection = false; + inputs.filters.forceHasTrendLineInside = true; + inputs.filters.forceHasTrendDirOnBothSide = false; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = true; + inputs.filters.filterBasedOnSignalBar = true; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "USDCHFb") + { + // + // Validators ... + inputs.validations.forceHasSwing = false; + inputs.validations.forceOBBarType = false; + inputs.validations.forceFVGBarType = false; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = true; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = true; + inputs.filters.filterBasedOnPV = true; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = false; + inputs.filters.forceSarOnBothSide = false; + inputs.filters.forceSarHasBreakout = true; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = true; + inputs.filters.forceHasRSITrending = true; + inputs.filters.forceHasRSIVPattern = true; + inputs.filters.forceHasRSICrossing = false; + inputs.filters.filterBasedOnADX = true; + inputs.filters.forceHasADXTrending = false; + inputs.filters.forceHasADXCrossing = false; + inputs.filters.filterBasedOnATR = false; + inputs.filters.forceHasATRTrending = false; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = false; + inputs.filters.forceHasTrendDir = false; + inputs.filters.forceHasTrendPlace = false; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = false; + inputs.filters.forceHasTrendRejection = false; + inputs.filters.forceHasTrendLineInside = true; + inputs.filters.forceHasTrendDirOnBothSide = true; + inputs.filters.filterBasedOnDelta = true; + inputs.filters.filterBasedOnVolume = true; + inputs.filters.filterBasedOnSignalBar = true; + inputs.filters.filterBasedOnHKSignalBar = true; + } + else if (inputs.symbol == "USDJPYb") + { + // + // Validators ... + inputs.validations.forceHasSwing = true; + inputs.validations.forceOBBarType = false; + inputs.validations.forceFVGBarType = false; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = false; + inputs.validations.validateBlockEdgeBreakout = true; + + // + // Filters ... + inputs.filters.filterBasedOnKI = true; + inputs.filters.filterBasedOnPV = false; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = true; + inputs.filters.forceSarOnBothSide = true; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = false; + inputs.filters.forceHasRSITrending = true; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = false; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = false; + inputs.filters.forceHasADXCrossing = false; + inputs.filters.filterBasedOnATR = false; + inputs.filters.forceHasATRTrending = false; + inputs.filters.forceHasATRBreakout = true; + inputs.filters.filterBasedOnTrend = false; + inputs.filters.forceHasTrendDir = false; + inputs.filters.forceHasTrendPlace = true; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = true; + inputs.filters.forceHasTrendRejection = false; + inputs.filters.forceHasTrendLineInside = true; + inputs.filters.forceHasTrendDirOnBothSide = false; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = false; + inputs.filters.filterBasedOnSignalBar = true; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "USDCADb") + { + // + // Validators ... + inputs.validations.forceHasSwing = true; + inputs.validations.forceOBBarType = true; + inputs.validations.forceFVGBarType = false; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = true; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = false; + inputs.filters.filterBasedOnPV = true; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = true; + inputs.filters.forceSarOnBothSide = true; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = true; + inputs.filters.forceHasRSITrending = false; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = false; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = false; + inputs.filters.forceHasADXCrossing = false; + inputs.filters.filterBasedOnATR = true; + inputs.filters.forceHasATRTrending = true; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = true; + inputs.filters.forceHasTrendDir = true; + inputs.filters.forceHasTrendPlace = true; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = true; + inputs.filters.forceHasTrendRejection = true; + inputs.filters.forceHasTrendLineInside = false; + inputs.filters.forceHasTrendDirOnBothSide = false; + inputs.filters.filterBasedOnDelta = true; + inputs.filters.filterBasedOnVolume = true; + inputs.filters.filterBasedOnSignalBar = true; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "NZDUSDb") + { + // + // Validators ... + inputs.validations.forceHasSwing = true; + inputs.validations.forceOBBarType = false; + inputs.validations.forceFVGBarType = false; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = false; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = true; + inputs.filters.filterBasedOnPV = false; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = true; + inputs.filters.forceSarOnBothSide = true; + inputs.filters.forceSarHasBreakout = false; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = false; + inputs.filters.forceHasRSITrending = true; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = true; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = true; + inputs.filters.forceHasADXCrossing = true; + inputs.filters.filterBasedOnATR = true; + inputs.filters.forceHasATRTrending = false; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = true; + inputs.filters.forceHasTrendDir = false; + inputs.filters.forceHasTrendPlace = false; + inputs.filters.forceHasTrendChange = false; + inputs.filters.forceHasTrendTrending = true; + inputs.filters.forceHasTrendRejection = true; + inputs.filters.forceHasTrendLineInside = true; + inputs.filters.forceHasTrendDirOnBothSide = true; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = false; + inputs.filters.filterBasedOnSignalBar = true; + inputs.filters.filterBasedOnHKSignalBar = false; + } + else if (inputs.symbol == "DJ30.spot") + { + // + // Validators ... + inputs.validations.forceHasSwing = true; + inputs.validations.forceOBBarType = false; + inputs.validations.forceFVGBarType = true; + inputs.validations.forceHasFLiquidity = false; + inputs.validations.forceHasRLiquidity = false; + inputs.validations.validateGapSequence = false; + inputs.validations.validateBlockEdgeBreakout = false; + + // + // Filters ... + inputs.filters.filterBasedOnKI = true; + inputs.filters.filterBasedOnPV = false; + inputs.filters.filterBasedOnSar = false; + inputs.filters.forceSarSwitched = true; + inputs.filters.forceSarOnBothSide = true; + inputs.filters.forceSarHasBreakout = true; + inputs.filters.forceSarHasReversalSide = true; + inputs.filters.filterBasedOnRSI = false; + inputs.filters.forceHasRSITrending = false; + inputs.filters.forceHasRSIVPattern = false; + inputs.filters.forceHasRSICrossing = true; + inputs.filters.filterBasedOnADX = false; + inputs.filters.forceHasADXTrending = true; + inputs.filters.forceHasADXCrossing = false; + inputs.filters.filterBasedOnATR = false; + inputs.filters.forceHasATRTrending = true; + inputs.filters.forceHasATRBreakout = false; + inputs.filters.filterBasedOnTrend = true; + inputs.filters.forceHasTrendDir = true; + inputs.filters.forceHasTrendPlace = false; + inputs.filters.forceHasTrendChange = true; + inputs.filters.forceHasTrendTrending = true; + inputs.filters.forceHasTrendRejection = false; + inputs.filters.forceHasTrendLineInside = false; + inputs.filters.forceHasTrendDirOnBothSide = false; + inputs.filters.filterBasedOnDelta = false; + inputs.filters.filterBasedOnVolume = false; + inputs.filters.filterBasedOnSignalBar = true; + inputs.filters.filterBasedOnHKSignalBar = false; + } + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/XCATBEA/Classes/xcatbea.signaller.class.mq5 b/BKPS/14040626/XCATBEA/Classes/xcatbea.signaller.class.mq5 new file mode 100644 index 0000000..779fc1e --- /dev/null +++ b/BKPS/14040626/XCATBEA/Classes/xcatbea.signaller.class.mq5 @@ -0,0 +1,2292 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCATBEASignaller ... +// Description: Class for XCATBEA Signaller ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCXCATBEASignaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-guard.class.mq5" +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" +#include "../Classes/xcatbea.x-poi.detector.class.mq5" +#include "../Classes/xcatbea.x-poi.drawer.class.mq5" +#include "../Libraries/xcatbea.lib.mq5" +#include "../Libraries/xcatbea.signaller.lib.mq5" +#include "../Libraries/xcatbea.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +// Configure Signalelrs ... +struct XCATBEASignallingConfigs +{ + // + // Signalling Method ... + bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions + bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks + bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs + + // + // Others ... + bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss + bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss + + // + // Market Conditions Signall Providers ... + bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + + // + // Constructor ... + XCATBEASignallingConfigs() + { + Clean(); + } + + // + // Tools ... + + // + // Cleaning Up ... + void Clean() + { + // + allowSignallingBasedOnConditions = false; + allowSignallingBasedOnTriggerBlocks = false; + allowSignallingBasedOnTriggerBlocksInsideOther = false; + + // + secondsTriggersSLUsingFirstTriggerBlock = false; + applyValidateAndFilterOnSelectInsideOthers = false; + + // + allowSignallingConditions1 = false; + allowSignallingConditions2 = false; + allowSignallingConditions3 = false; + allowSignallingConditions4 = false; + allowSignallingConditions5 = false; + allowSignallingConditions6 = false; + } +}; + +// +struct XCATBEASignallerInputs +{ + // + // Pros ... + string symbol; + string provider; + bool allowDraws; + bool allowGuards; + int riskToRewardRatio; + ENUM_TIMEFRAMES period; + double slATRMultiplier; + X121XCatbInputs catbInputs; + XTriggerBlockFilters filters; + XTriggerBlockValidationRules validations; + XCATBEASignallingConfigs signallerConfigs; + + // + // Constructor(s) ... + XCATBEASignallerInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + period = NULL; + provider = NULL; + filters.Clean(); + catbInputs.Clean(); + allowDraws = false; + validations.Clean(); + allowGuards = false; + slATRMultiplier = 0; + riskToRewardRatio = 0; + signallerConfigs.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(provider) && + catbInputs.IsValid() && + riskToRewardRatio > 0; + + // + return result; + } + + // +}; + +// +// Implementations ... +class XCXCATBEASignaller : XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + int maxAllowedSetupAge; // Maximum Allowed Setup Age for Living + + // + bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions + bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks + bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs + + // + bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss + bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss + + // + // Market Conditions Signall Providers ... + bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + + // + bool allowDraws; // Allow Draws or not ... + bool allowGuards; // Allow Guards or not ... + int riskToRewardRatio; // Signals R2R ... + double slATRMultiplier; // SL ATR Multiplier ... + + // + XCX121XCatbHelper *helper; // XCATB Helper Class instance ... + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCXCATBEAPOIDrawer *drawer; // POI Drawer ... + XBarTracker ticksBarTracker; // Bar Tracker ... + XTriggerBlockFilters filters; // Trigger Block Filters ... + XCXCATBEAPOIDetector *detector; // POI Detector ... + XTriggerBlockValidationRules validations; // Trigger Block Validations ... + + // + XBoxZone cPeak; // Current Peak ... + XBoxZone cVale; // Current Vale ... + XBoxZone unavailableZones[]; // Un Available Zones ... + XTriggerBlock cTriggerBlock; // Currently Selected Trigger Block ... + XTriggerBlock triggerBlocks[]; // Founded Trigger Blocks ... + bool waitsUntilPeakInvalidate; // Waits Until Peak Invalidate ... + bool waitsUntilValeInvalidate; // Waits Until Vale Invalidate ... + XTriggerBlock cInsideTriggerBlock; // a TriggerBlock which Currently Selected Trigger Block is Inside it ... + + // + XCATBEAStrategyConditions mConditions; + XCATBEAStrategyConditions mConditionsCollection[]; + + // + // Constructor ... + XCXCATBEASignaller(XCATBEASignallerInputs &inputs) + { + Init(inputs); + } + + // + // Deconstructor ... + ~XCXCATBEASignaller() + { + DeInit(); + } + + // + // Properties ... + + // + string GetSymbol() + { + return symbol; + } + + // + string GetProvider() + { + return provider; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return period; + } + + // + double GetR2R() + { + return riskToRewardRatio; + } + + // + // Tick Analyser ... + + /** + * Process Tick ... + */ + void ProcessTick( + XPosition &positions[], + XGuard &guards[], + XCATBEAStrategyConditions &conditions, + bool isActiveSession = true // + ) + { + // + Clean(guards); + conditions.Clean(); + + // + XOHCL bar; + int count = 0; + bool has = false; + int barIndex = 0; + cTriggerBlock.Clean(); + cInsideTriggerBlock.Clean(); + + // + // Check Guards ... + has = DetectGuards( + guards, + positions, + barIndex // + ); + + // + // Check Bar Processing ... + if (!ticksBarTracker.CanProcessBar()) + { + return; + } + + // + // Check Triggered Conditions ... + has = HasChild(mConditionsCollection); + if (has) + { + // + int selectedIDX = -1; + count = ArraySize(mConditionsCollection); + for (int i = 0; i < count; i++) + { + // + // Select indexed Conditions ... + XCATBEAStrategyConditions iConditions = mConditionsCollection[i]; + + // + // Check Conditions Triggered ... + has = DetectSignalTrigger( + iConditions, + barIndex // + ); + if (has) + { + // + selectedIDX = i; + conditions = iConditions; + iConditions.Clean(); + + // + break; + } + + // + // When Setup Invalidated + // Signaller Clean Conditions ... + if (!has && + !iConditions.IsValid()) + { + // + selectedIDX = i; + break; + } + + // + // Cleanup Resources ... + iConditions.Clean(); + } + + // + // Check Can Trigger ... + has = IsValidIndex(selectedIDX) && + conditions.IsValid() && + conditions.IsSetuped() && + conditions.CanTrigger(); + if (has) + { + // + ArrayRemove( + mConditionsCollection, + selectedIDX, + 1 // + ); + } + else + { + // + // Check Selected Index for Invalid Conditions ... + if (IsValidIndex(selectedIDX)) + { + // + // Remove Invalidated Conditions ... + ArrayRemove( + mConditionsCollection, + selectedIDX, + 1 // + ); + } + + // + // Cleanup Resource ... + conditions.Clean(); + } + } + + // + // Initialize Bar ... + bar.Init( + symbol, + period, + barIndex // + ); + + // + // Detect POI(s) ... + detector.Detect(barIndex); + + // + // Validate POI(s) ... + detector.Validate( + unavailableZones, + barIndex // + ); + + // + // Check Helper Last Changes ... + helper.Check(barIndex); + + // + // Draw POI(s) ... + if (allowDraws) + { + // drawer.Draw(bar.time); + } + + // + // Detect Trigger Blocks and Collect them ... + XTriggerBlock iTriggerBlock; + X121XCatbConditions iConditions; + XTriggerBlockFilters iFilters; + XTriggerBlockValidationRules iValidations; + if (applyValidateAndFilterOnSelectInsideOthers) + { + // + // Validations ... + iValidations.forceHasSwing = validations.forceHasSwing; + iValidations.forceOBBarType = validations.forceOBBarType; + iValidations.forceFVGBarType = validations.forceFVGBarType; + iValidations.maxAllowedRange = validations.maxAllowedRange; + iValidations.minAllowedRange = validations.minAllowedRange; + iValidations.minRequiredOBBar = validations.minRequiredOBBar; + iValidations.liquidityLoopback = validations.liquidityLoopback; + iValidations.forceHasFLiquidity = validations.forceHasFLiquidity; + iValidations.forceHasRLiquidity = validations.forceHasRLiquidity; + iValidations.validateGapSequence = validations.validateGapSequence; + iValidations.minAllowedBlockLength = validations.minAllowedBlockLength; + iValidations.validateBlockEdgeBreakout = validations.validateBlockEdgeBreakout; + + // + // Clone Filters and Validations ... + iFilters.bosLoopback = filters.bosLoopback; + iFilters.filterBasedOnKI = filters.filterBasedOnKI; + iFilters.filterBasedOnPV = filters.filterBasedOnPV; + iFilters.filterBasedOnSar = filters.filterBasedOnSar; + iFilters.filterBasedOnRSI = filters.filterBasedOnRSI; + iFilters.filterBasedOnADX = filters.filterBasedOnADX; + iFilters.filterBasedOnATR = filters.filterBasedOnATR; + iFilters.forceSarSwitched = filters.forceSarSwitched; + iFilters.forceHasTrendDir = filters.forceHasTrendDir; + iFilters.filterBasedOnTrend = filters.filterBasedOnTrend; + iFilters.filterBasedOnDelta = filters.filterBasedOnDelta; + iFilters.forceSarOnBothSide = filters.forceSarOnBothSide; + iFilters.forceHasTrendPlace = filters.forceHasTrendPlace; + iFilters.forceSarHasBreakout = filters.forceSarHasBreakout; + iFilters.filterBasedOnVolume = filters.filterBasedOnVolume; + iFilters.forceHasRSITrending = filters.forceHasRSITrending; + iFilters.forceHasRSIVPattern = filters.forceHasRSIVPattern; + iFilters.forceHasRSICrossing = filters.forceHasRSICrossing; + iFilters.forceHasADXTrending = filters.forceHasADXTrending; + iFilters.forceHasADXCrossing = filters.forceHasADXCrossing; + iFilters.forceHasATRTrending = filters.forceHasATRTrending; + iFilters.forceHasATRBreakout = filters.forceHasATRBreakout; + iFilters.forceHasTrendChange = filters.forceHasTrendChange; + iFilters.forceHasTrendTrending = filters.forceHasTrendTrending; + iFilters.forceHasTrendRejection = filters.forceHasTrendRejection; + iFilters.filterBasedOnSignalBar = filters.filterBasedOnSignalBar; + iFilters.forceHasTrendLineInside = filters.forceHasTrendLineInside; + iFilters.forceSarHasReversalSide = filters.forceSarHasReversalSide; + iFilters.filterBasedOnHKSignalBar = filters.filterBasedOnHKSignalBar; + iFilters.forceHasTrendDirOnBothSide = filters.forceHasTrendDirOnBothSide; + } + has = DetectTriggerBlock( + helper, + barAnalyser, + iTriggerBlock, + iConditions, + iValidations, + iFilters, + barIndex, + 10 // Loopback ... + ); + if (has) + { + // + // Add Trigger Block to Collection if not Exists ... + AddIfNotExists( + iTriggerBlock, + triggerBlocks // + ); + } + iFilters.Clean(); + iConditions.Clean(); + iValidations.Clean(); + iTriggerBlock.Clean(); + + // + // Draw Trigger Blocks ... + if (allowDraws) + { + // + // Handle To Updating ... + // datetime cTime = TimeCurrent(); + // DrawTriggerBlocks(cTime); + } + + // + // Here we Check Active Session ... + // and Prevent Moving forward if there is not + // Session actives ... + // for improvement Calculation Speeds ... + if (isActiveSession) + { + // + // Check Signal Setups ... + has = DetectSignalSetup(barIndex); + if (has) + { + // + ticksBarTracker.Waits(); + + // + AddConditionsIfNotExists(); + + // + mConditions.Clean(); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + } + + // + // Signalling Tools ... + + /** + * Detect Setup Conditions based on Signalling ... + * + * @param maxAllowedSLDistanceInPoint: int, Max Allowed SL Distance in Points (if Bigger thn Zero Provided) ... + * + * @return ( bool ) + */ + bool DetectSignalSetup(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update All Required Buffers ... + helper.Update(barIndex); + + // + bool has = false; + datetime cTime = TimeCurrent(); + + // + // cPeak and cVale ... + // these Helpes Us to Detect Price Levels ... + // + // Draw Peak and Vale if Exists ... + + // + // Peak ... + if (cPeak.IsValid()) + { + // + cPeak.to = cTime; + // drawer.DrawBox(cPeak); + } + + // + // Vale ... + if (cVale.IsValid()) + { + // + cVale.to = cTime; + // drawer.DrawBox(cVale); + } + + // + // Try to Validate cPeak an cVale if Exists ... + XOHCL zBar; + XOHCL cBar; + bool isInited = zBar.Init( + symbol, + period, + barIndex // + ); + isInited = zBar.GetPreviousBar(cBar); + isInited = helper.GetConditions( + mConditions.conditions, + barIndex, + 10 // + ); + if (isInited) + { + // + // Validate cPeak and cVale if Exists ... + + // + // cPeak ... + if (cPeak.IsValid()) + { + // + isInited = cBar.high < cPeak.lower; + if (!isInited) + { + // + cPeak.Clean(); + cVale.Clean(); + + // + waitsUntilPeakInvalidate = false; + waitsUntilValeInvalidate = false; + } + } + + // + // cVale ... + if (cVale.IsValid()) + { + // + isInited = cBar.low > cVale.upper; + if (!isInited) + { + // + cPeak.Clean(); + cVale.Clean(); + + // + waitsUntilPeakInvalidate = false; + waitsUntilValeInvalidate = false; + } + } + + // + // Try To Detect Peak and Vale based on cBar ... + + // + // Selecting Peak ... + if (!cPeak.IsValid()) + { + // + XBoxZone tmpPeaks[]; + detector.FillPeakPivots(tmpPeaks); + while (HasChild(tmpPeaks)) + { + // + // Find Index ... + int idx = GetLowest(tmpPeaks); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cPeak = tmpPeaks[idx]; + ArrayRemove( + tmpPeaks, + idx, + 1 // + ); + + // + // Validate Peak ... + bool isValid = cPeak.lower > cBar.high; + if (isValid) + { + break; + } + + // + cPeak.Clean(); + } + Clean(tmpPeaks); + } + + // + // Selecting Vale ... + if (!cVale.IsValid()) + { + // + XBoxZone tmpVales[]; + detector.FillValePivots(tmpVales); + while (HasChild(tmpVales)) + { + // + // Find Index ... + int idx = GetHighest(tmpVales); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cVale = tmpVales[idx]; + ArrayRemove( + tmpVales, + idx, + 1 // + ); + + // + // Validate Vale ... + bool isValid = cVale.upper < cBar.low; + if (isValid) + { + break; + } + + // + cVale.Clean(); + } + Clean(tmpVales); + } + } + + // + // Detect Signal Setup Based on Market Conditions ... + if (!result && + allowSignallingBasedOnConditions) + { + // + // Detect Signalling Zone ... + result = DetectSignalZone( + helper, + drawer, + detector, + barAnalyser, + mConditions.conditions, + mConditions.pivotZone, + allowSignallingConditions1, + allowSignallingConditions2, + allowSignallingConditions3, + allowSignallingConditions4, + allowSignallingConditions5, + allowSignallingConditions6, + barIndex, + 10 // Loopback ... + ); + if (result) + { + // + // Use Signal Zone ... + UseBox(mConditions.pivotZone); + + // + // Prepare Condition ... + + // + // Prepare Signal ... + mConditions.dir = + mConditions + .pivotZone + .dir; + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.provider = provider; + mConditions.reward = riskToRewardRatio; + mConditions.time = mConditions.conditions.bars[0].time; + mConditions.setupTime = mConditions.conditions.bars[0].time; + + // + // Prepare Target ... + double targets[]; + for (int i = 1; i <= riskToRewardRatio; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + // Calculate SL Additions ... + double iATR = 0; + if (barIndex > 0 && + barIndex < ArraySize(helper.atrBuffer)) + { + iATR = helper.atrBuffer[barIndex]; + } + double slAdditional = slATRMultiplier * iATR; + + // + // Preparing Signal ... + XSignal iSignal; + result = ToSignal( + mConditions.pivotZone, + iSignal, + targets, + slAdditional // + ); + if (result) + { + // + mConditions.sl = iSignal.sl; + mConditions.tp = iSignal.tp; + mConditions.pivot = iSignal.sl; + mConditions.entry = iSignal.entry; + mConditions.point = iSignal.entry; + mConditions.type = ToPositionType(iSignal.type); + + // + // Draw Trigger Block ... + if (allowDraws) + { + // + XCBoxObject *iObj; + has = drawer + .drawer + .DrawBox( + mConditions.pivotZone, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + ZeroMemory(iObj); + } + } + iSignal.Clean(); + } + } + + // + // Detect Signal Setup Based on Trigger Block Detection ... + if (!result && + allowSignallingBasedOnTriggerBlocks) + { + // + // Detect Trigger Block ... + result = DetectTriggerBlock( + helper, + barAnalyser, + mConditions.triggerBlock, + mConditions.conditions, + validations, + filters, + barIndex, + 10 // Loopback ... + ); + if (result) + { + // + // Use Trigger Block ... + UseTriggerBlock(mConditions.triggerBlock); + + // + // Prepare Condition ... + + // + // Prepare Signal ... + mConditions.dir = + mConditions + .triggerBlock + .GetDirection(); + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.provider = provider; + mConditions.reward = riskToRewardRatio; + mConditions.time = mConditions.conditions.bars[0].time; + mConditions.setupTime = mConditions.conditions.bars[0].time; + + // + // Prepare Target ... + double targets[]; + for (int i = 1; i <= riskToRewardRatio; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + // Calculate SL Additions ... + double iATR = 0; + if (barIndex > 0 && + barIndex < ArraySize(helper.atrBuffer)) + { + iATR = helper.atrBuffer[barIndex]; + } + double slAdditional = slATRMultiplier * iATR; + + // + // Preparing Signal ... + result = ToSignal( + mConditions.triggerBlock.trigger, + mConditions.triggerBlock.signal, + targets, + slAdditional // + ); + if (result) + { + // + mConditions.triggerBlock.signal.provider = provider; + mConditions.sl = mConditions.triggerBlock.signal.sl; + mConditions.tp = mConditions.triggerBlock.signal.tp; + mConditions.pivot = mConditions.triggerBlock.signal.sl; + mConditions.entry = mConditions.triggerBlock.signal.entry; + mConditions.point = mConditions.triggerBlock.signal.entry; + mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type); + + // + // Draw Trigger Block ... + if (allowDraws) + { + // + DrawTriggerBlock( + mConditions.triggerBlock, + drawer.drawer, + mObjects, + NULL, // To ... + false // Draw Signal ... + ); + } + } + } + } + + // + // Detect Signal Setup Based On Trigger Blocks Second Entry ... + if (!result && + allowSignallingBasedOnTriggerBlocksInsideOther) + { + // + // Trigger Block Detection ... + result = HasChild(triggerBlocks) && + ArraySize(triggerBlocks) > 1 && + !waitsUntilPeakInvalidate && + !waitsUntilValeInvalidate; + if (result) + { + // + // Check Newest Trigger Block ... + bool isTriggerBlockSelected = false; + XTriggerBlock tmpTBs[]; + Copy( + triggerBlocks, + tmpTBs // + ); + while (HasChild(tmpTBs)) + { + // + int idx = GetYoungest(tmpTBs); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + // and Remove From Collection ... + cTriggerBlock = tmpTBs[idx]; + ArrayRemove( + tmpTBs, + idx, + 1 // + ); + + // + // Validate ... + isTriggerBlockSelected = + // + // Check Bar is Valid ... + cBar.IsValid() && + // + // Currently Happens ... + (cTriggerBlock.trigger.to == zBar.time || + cTriggerBlock.trigger.to == cBar.time) && + // + // Price Validations ... + (cTriggerBlock.IsBullish() + ? cBar.low > cTriggerBlock.trigger.lower + : cBar.high < cTriggerBlock.trigger.upper) + // + ; + if (isTriggerBlockSelected) + { + break; + } + + // + // Clean Trigger Block ... + cTriggerBlock.Clean(); + } + Clean(tmpTBs); + + // + // Check Trigger Block Selection ... + result = isTriggerBlockSelected; + if (result) + { + // + bool isBullish = cTriggerBlock.IsBullish(); + bool isBearish = cTriggerBlock.IsBearish(); + + // + // Now we have to Check Newest Trigger Block Place ... + int insideTBIDX = DetectInsideTriggerBlock( + cTriggerBlock, + cInsideTriggerBlock, + triggerBlocks // + ); + + // + // Check InsideTB is Exists and Valid ... + result = + cInsideTriggerBlock.IsValid() && + IsValidIndex(insideTBIDX); + if (result) + { + // + // Now we Have to Detect Peak and Vales ... + result = + cPeak.IsValid() && + cVale.IsValid(); + + // + // If Exists Before Validate them based Trigger Blocks ... + if (result) + { + // + // Validate cPeak and cVale based on + // cTriggerBlock and cInsideTriggerBlock ... + result = + // + // Peak ... + cPeak.lower > cTriggerBlock.trigger.upper && + cPeak.lower > cInsideTriggerBlock.trigger.upper && + // + // Vale ... + cVale.upper < cTriggerBlock.trigger.lower && + cVale.upper < cInsideTriggerBlock.trigger.lower && + // + // Bar Validation ... + cBar.IsValid() && + cBar.low > cVale.upper && + cBar.high < cPeak.lower + // + ; + if (!result) + { + // + cPeak.Clean(); + cVale.Clean(); + + // + waitsUntilPeakInvalidate = false; + waitsUntilValeInvalidate = false; + } + } + + // + // if not Exists, or Clean them on Invalidating Process, try to Find Corrects ... + if (!result) + { + // + // Selecting Peak ... + XBoxZone tmpPeaks[]; + detector.FillPeakPivots(tmpPeaks); + while (HasChild(tmpPeaks)) + { + // + // Find Index ... + int idx = GetLowest(tmpPeaks); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cPeak = tmpPeaks[idx]; + ArrayRemove( + tmpPeaks, + idx, + 1 // + ); + + // + // Validate Peak ... + bool isValid = + // + // Bar Validation ... + cBar.IsValid() && + cBar.high < cPeak.lower && + // + // Peak Validation ... + cPeak.lower > cTriggerBlock.trigger.upper && + cPeak.lower > cInsideTriggerBlock.trigger.upper; + if (isValid) + { + break; + } + + // + cPeak.Clean(); + } + Clean(tmpPeaks); + + // + // Selecting Vale ... + XBoxZone tmpVales[]; + detector.FillValePivots(tmpVales); + while (HasChild(tmpVales)) + { + // + // Find Index ... + int idx = GetHighest(tmpVales); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cVale = tmpVales[idx]; + ArrayRemove( + tmpVales, + idx, + 1 // + ); + + // + // Validate Vale ... + bool isValid = + // + // Bar Validation ... + cBar.IsValid() && + cBar.low > cVale.upper && + // + // Vale Validation ... + cVale.upper < cTriggerBlock.trigger.lower && + cVale.upper < cInsideTriggerBlock.trigger.lower; + if (isValid) + { + break; + } + + // + cVale.Clean(); + } + Clean(tmpVales); + + // + // Summarizing Result ... + result = + cPeak.IsValid() && + cVale.IsValid(); + } + + // + // Check Peak and Vale Exists ... + if (result) + { + // + // Remove Peak from Detector Collections ... + // and Make it unavailable ... + UseBox(cPeak); + + // + // Remove Vale from Detector Collections ... + // and Make it unavailable ... + UseBox(cVale); + + // + // Remove Selected Trigger Block ... + // and Make it unavailable ... + RemoveTriggerBlock( + cTriggerBlock, + triggerBlocks // + ); + UseTriggerBlock(cTriggerBlock); + + // + // Remove Selected Inside Trigger Block ... + // and Make it unavailable ... + RemoveTriggerBlock( + cInsideTriggerBlock, + triggerBlocks // + ); + UseTriggerBlock(cInsideTriggerBlock); + + // + // Update Peak and Vales To ... + cPeak.to = cTime; + cVale.to = cTime; + + // + // Draw Peak and Vales ... + if (allowDraws) + { + // + drawer.DrawBox(cPeak); + drawer.DrawBox(cVale); + } + + // + // Validate Peaks and Vales ... + bool isPeakPassed = false; + bool isValePassed = false; + cInsideTriggerBlock.trigger.to = cTime; + int toIDX = cInsideTriggerBlock.ToIndex(); + int fromIDX = cInsideTriggerBlock.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Reading Values ... + + // + double iPeak = helper.GetPeak(i); + double iPPeak = helper.GetPeak(i + 1); + + // + double iVale = helper.GetVale(i); + double iPVale = helper.GetVale(i + 1); + + // + bool isPeakOverLast = iPeak > iPPeak; + bool isPeakUnderLast = iPeak < iPPeak; + + // + bool isValeOverLast = iVale > iPVale; + bool isValeUnderLast = iVale < iPVale; + + // + if (!isPeakPassed) + { + // + isPeakPassed = + isBullish ? isPeakOverLast + : isPeakUnderLast; + } + + // + if (!isValePassed) + { + // + isValePassed = + isBullish + ? isValeUnderLast + : isPeakOverLast; + } + + // + result = + isPeakPassed && + isValePassed; + if (result) + { + break; + } + } + if (result) + { + // + // Draw Trigger Blocks if Allowed ... + if (allowDraws) + { + // + // Draw Blocks ... + + // + // mObjects.Clear(); + + // + // Detected Block ... + DrawTriggerBlock( + cTriggerBlock, + drawer.drawer, + mObjects, + cTime, + false // Draw Signal ... + ); + + // + // Inside Block ... + DrawTriggerBlock( + cInsideTriggerBlock, + drawer.drawer, + mObjects, + cTime, + false // Draw Signal ... + ); + } + + // + if (isBullish) + { + waitsUntilPeakInvalidate = true; + } + else if (isBearish) + { + waitsUntilValeInvalidate = true; + } + + // + mConditions.triggerBlock = cTriggerBlock; + } + } + } + } + } + + // + // Preparing Conditions based on result ... + if (result) + { + // + bool isBullish = mConditions.triggerBlock.IsBullish(); + + // + // Preparing mConditions ... + mConditions.dir = + mConditions + .triggerBlock + .GetDirection(); + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.provider = provider; + mConditions.reward = riskToRewardRatio; + mConditions.time = mConditions.conditions.bars[0].time; + mConditions.setupTime = mConditions.conditions.bars[0].time; + + // + // Prepare Target ... + double targets[]; + for (int i = 1; i <= riskToRewardRatio; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + // Calculate SL Additions ... + double iATR = 0; + if (barIndex > 0 && + barIndex < ArraySize(helper.atrBuffer)) + { + iATR = helper.atrBuffer[barIndex]; + } + double slAdditional = slATRMultiplier * iATR; + + // + // Preparing Signal ... + result = ToSignal( + mConditions.triggerBlock.trigger, + mConditions.triggerBlock.signal, + targets, + slAdditional // + ); + XSignal insideTBSignal; + result = + result && + ToSignal( + cInsideTriggerBlock.trigger, + insideTBSignal, + targets, + slAdditional // + ); + if (result) + { + // + // Try to Use SL Based on Inside Trigger Block ... + double sl = 0; + double tp = 0; + if (secondsTriggersSLUsingFirstTriggerBlock) + { + // + sl = insideTBSignal.sl; + tp = insideTBSignal.tp; + + // + // Add Target for usuall Signal TP ... + XTarget iTarget; + iTarget.doRF = true; + iTarget.target = mConditions.triggerBlock.signal.tp; + + // + AddRef( + iTarget, + mConditions.targets); + + // + iTarget.Clean(); + } + else + { + // + sl = mConditions.triggerBlock.signal.sl; + tp = mConditions.triggerBlock.signal.tp; + } + + // + mConditions.sl = sl; + mConditions.tp = tp; + mConditions.pivot = sl; + mConditions.triggerBlock.signal.provider = provider; + mConditions.entry = mConditions.triggerBlock.signal.entry; + mConditions.point = mConditions.triggerBlock.signal.entry; + mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type); + + // + // Draw Trigger Block ... + if (allowDraws) + { + // + DrawTriggerBlock( + mConditions.triggerBlock, + drawer.drawer, + mObjects, + NULL, // To ... + false // Draw Signal ... + ); + } + } + } + } + + // + // Check a Signal Setup Exists or not ... + result = mConditions.IsValid() && + mConditions.IsSetuped(); + + // + // Cleanup Resource ... + zBar.Clean(); + cBar.Clean(); + cTriggerBlock.Clean(); + cInsideTriggerBlock.Clean(); + + // + return result; + } + + /** + * Detect Trigger Conditions for Specified Signal ... + * + * @param conditions: XCATBEAStrategyConditions instance Reference, Specified Signal Conditions ... + * @param barIndex: int, Bar Index ... + * + * @return ( bool ) + */ + bool DetectSignalTrigger( + XCATBEAStrategyConditions &conditions, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Setup ... + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + bool has = false; + datetime cTime = TimeCurrent(); + bool isBullish = IsBullish(conditions.dir); + bool isBearish = IsBearish(conditions.dir); + + // + bool isBasedOnPivotZone = conditions.pivotZone.IsValid(); + bool isBasedOnTriggerBlock = conditions.triggerBlock.IsValid(); + + // + // Reading Current Market Conditions ... + X121XCatbConditions cConditions; + result = + result && + helper.GetConditions( + cConditions, + barIndex, + 10 // + ); + + // + // Validate Direction of Setuped Conditions ... + result = + result && + (isBullish || + isBearish); + + // + // Detecting Trigger Bar ... + + // + ENUM_X_DIRECTION triggerDir; + bool isTriggerBar = barAnalyser + .IsValidForTrigger( + cConditions.bars[0], + triggerDir, + true, // Allow Cond 1 ... + true, // Allow Cond 2 ... + true, // Allow Cond 3 ... + true, // Allow Cond 4 ... + true, // Allow Cond 5 ... + true, // Allow Cond 6 ... + true // Allow Cond 7 ... + // + ); + bool isBullishTriggerBar = + isTriggerBar && + IsBullish(triggerDir); + bool isBearishTriggerBar = + isTriggerBar && + IsBearish(triggerDir); + + // + // Do Triggering Senario based on Trigger Block ... + if (result && + isBasedOnTriggerBlock) + { + // + // Checking Score ... + double bullishScore = 0; + double bearishScore = 0; + conditions + .conditions + .GenerateScore( + bullishScore, + bearishScore // + ); + bool isScorePassed = + isBullish + ? bullishScore > bearishScore + : bearishScore > bullishScore; + + // + // Complete Conditions Here ... + if (isScorePassed) + { + conditions.triggerTime = TimeCurrent(); + } + } + + // + // Do Triggering based on Market Conditions PivotZones ... + if (result && + isBasedOnPivotZone) + { + // + // Update Box To ... + conditions.pivotZone.to = cTime; + + // + DrawPivotZone(conditions.pivotZone); + + // + // Trigger on Detection Time ... + bool triggerPivotZonesOnSetupTime = true; + if (triggerPivotZonesOnSetupTime) + { + // + conditions.triggerTime = TimeCurrent(); + } + else + { + // + // Check atleast 3 Bars Close Outside of applied Edge ... + // Check Current Bar is a Trigger Bar ... + // TODO: Complete this ... + + // + // Checking Score ... + double bullishScore = 0; + double bearishScore = 0; + cConditions + .GenerateScore( + bullishScore, + bearishScore // + ); + bool isScorePassed = + isBullish + ? bullishScore > bearishScore + : bearishScore > bullishScore; + // true; + + // + // Check Bar is Inside Zone ... + bool isBarInside = + (isBullish + ? (cConditions.bars[1].low < conditions.pivotZone.upper && + cConditions.bars[1].low > conditions.pivotZone.lower) + : (cConditions.bars[1].high > conditions.pivotZone.lower && + cConditions.bars[1].high < conditions.pivotZone.upper)); + + // + // Checking Conditions Requirements ... + + // + bool isConditionsBullishPowered = + // + // Trend ... + (cConditions.isTrendBullish || + (!cConditions.isTrendBullish && + !cConditions.isTrendBearish)); + + // + bool isConditionsBearishPowered = + // + // Trend ... + (cConditions.isTrendBearish || + (!cConditions.isTrendBullish && + !cConditions.isTrendBearish)); + + // + isBullish = + isBullish && + isBarInside && + isScorePassed && + isBullishTriggerBar && + isConditionsBullishPowered; + + // + isBearish = + isBearish && + isBarInside && + isScorePassed && + isBearishTriggerBar && + isConditionsBearishPowered; + + // + result = isBullish || + isBearish; + result = false; + if (result) + { + + // + // Check Bar is Touched Zone Middle or not ... + double mid = conditions.pivotZone.GetMid(); + bool isMiddlePassed = + isBullish + ? (cConditions.bars[1].low < mid && + cConditions.bars[1].GetDown() > mid) + : (cConditions.bars[1].high > mid && + cConditions.bars[1].GetUp() < mid); + + // + // Ignore Box Middle Pass ... + // result = + // result && + // isMiddlePassed; + + // + if (result) + { + // + // Print("Trigger Bar Detected ..."); + conditions.triggerTime = TimeCurrent(); + } + } + } + } + + // + // Do Other Validation Senarios ... + + // + result = conditions.IsValid() && + conditions.IsSetuped() && + conditions.CanTrigger(); + + // + // Check Setup Age or Setup Validations here ... + if (!result) + { + // + // Validate Trigger Block Based Setups ... + + // + // Validate Pivot Zone Based Setups ... + if (isBasedOnPivotZone) + { + // + // Check Box Breaked ... + has = IsSignalZoneBreaked( + helper, + conditions.pivotZone, + barIndex // + ); + if (has) + { + conditions.Clean(); + } + } + + // + // Validate Setup Age ... + int age = conditions.GetSetupAge(); + bool has = maxAllowedSetupAge > 0 && + age <= maxAllowedSetupAge; + if (!has) + { + conditions.Clean(); + } + } + + // + // Cleanup Resources ... + + // + return result; + } + + /** + * Detect Guards bsed on Signalling Class ... + * + * @param guards: XCAEAGuard instance Collection, Holds Provided Guards ... + * @param positions: XPosition instance Collection, Provides Signalling Based Positions for Apply Guards on them ... + * @param provider: X121SMCStrategySignalProviderData instance Reference, Specified Data for Cycles ... + * + * @return ( bool ) + */ + bool DetectGuards( + XGuard &guards[], + const XPosition &positions[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + Clean(guards); + barIndex = NormalizeInt(barIndex, 0); + + // + result = allowGuards && + HasChild(positions); + if (!result) + { + return result; + } + + // + // TODO: Implement this ... + + // + result = HasChild(guards); + + // + // Cleanup Resources ... + + // + if (!result) + { + Clean(guards); + } + + // + return result; + } + + // + // Protected ... + protected: + // + + /** + * Initialize ... + */ + void Init(XCATBEASignallerInputs &inputs) + { + // + maxAllowedSetupAge = 288; + maxAllowedCollection = 100; + + // + allowSignallingBasedOnConditions = inputs.signallerConfigs.allowSignallingBasedOnConditions; + allowSignallingBasedOnTriggerBlocks = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks; + allowSignallingBasedOnTriggerBlocksInsideOther = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther; + + // + secondsTriggersSLUsingFirstTriggerBlock = inputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock; + applyValidateAndFilterOnSelectInsideOthers = inputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers; + + // + allowSignallingConditions1 = inputs.signallerConfigs.allowSignallingConditions1; + allowSignallingConditions2 = inputs.signallerConfigs.allowSignallingConditions2; + allowSignallingConditions3 = inputs.signallerConfigs.allowSignallingConditions3; + allowSignallingConditions4 = inputs.signallerConfigs.allowSignallingConditions4; + allowSignallingConditions5 = inputs.signallerConfigs.allowSignallingConditions5; + allowSignallingConditions6 = inputs.signallerConfigs.allowSignallingConditions6; + + // + bool has = inputs.IsValid(); + if (!has) + { + return; + } + + // + symbol = inputs.symbol; + period = inputs.period; + filters = inputs.filters; + provider = inputs.provider; + allowDraws = inputs.allowDraws; + allowGuards = inputs.allowGuards; + validations = inputs.validations; + slATRMultiplier = inputs.slATRMultiplier; + riskToRewardRatio = inputs.riskToRewardRatio; + + // + mObjects = new CArrayObj(); + + // + // Initialize Bar Tracker ... + has = ticksBarTracker.Init( + symbol, + period // + ); + if (!has) + { + return; + } + + // + + // + // Initialize Bar Analyser ... + barAnalyser = new XCBarAnalyser(); + + // + // initialize Helper ... + helper = new XCX121XCatbHelper(); + has = helper.Init( + symbol, + period, + inputs.catbInputs // + ); + if (!has) + { + return; + } + + // + mConditions.Clean(); + Clean(mConditionsCollection); + + // + InitPOI(); + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + mObjects.Clear(); + delete mObjects; + ZeroMemory(mObjects); + + // + drawer.Clear(); + delete drawer; + ZeroMemory(drawer); + + // + detector.CleanPivots(); + delete detector; + ZeroMemory(detector); + + // + delete helper; + ZeroMemory(helper); + + // + delete barAnalyser; + ZeroMemory(barAnalyser); + + // + ticksBarTracker.Clean(); + } + + /** + * Add Conditions to Conditions Collection if not Exists ... + * + * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... + * + * @return ( int ) + */ + int AddConditionsIfNotExists( + int maxAllowed = 50 // + ) + { + // + int result = 0; + + // + // Normalize Args ... + maxAllowed = maxAllowedCollection; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + XCATBEAStrategyConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + XCATBEAStrategyConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + /** + * Add TriggerBlock if not Exists + * inside a Collection ... + */ + int AddIfNotExists( + XTriggerBlock &tb, + XTriggerBlock &tbs[], + int maxAllowed = 50 // + ) + { + // + int result = 0; + + // + // Normalize Args ... + maxAllowed = maxAllowedCollection; + + // + // First Validate ... + if (!tb.IsValid()) + { + return result; + } + + // + // Check Exists ... + // and prevent moving forward if exists ... + int idx = -1; + bool isExists = FindTriggerBlockIndex( + idx, + tb, + tbs // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + // Add if not Exists ... + AddRef( + tb, + tbs // + ); + + // + // Cleanup ... + CleanupArray( + tbs, + maxAllowed // + ); + + // + result = ArraySize(tbs); + + // + return result; + } + + /** + * Use Specified Box and make it Unavailable ... + * + * @param box: XBoxZone instance reference ... + */ + void UseBox(XBoxZone &box) + { + // + // Validate Box ... + bool has = box.IsValid(); + if (!has) + { + return; + } + + // + // Check Box Added Before or not ... + int idx = -1; + has = FindIndex( + idx, + box, + unavailableZones // + ); + if (has) + { + return; + } + + // + // Adding Box Reference to + // Unavailable Zones ... + AddRef( + box, + unavailableZones // + ); + + // + // Cleanup Array ... + CleanupArray( + unavailableZones, + maxAllowedCollection // + ); + + // + } + + /** + * Use Specified Trigger Block and Make it Un Available ... + * + * @param tb: XTriggerBlock instance reference, Specified Used Trigger Block ... + */ + void UseTriggerBlock(XTriggerBlock &tb) + { + // + bool has = tb.IsValid(); + if (!has) + { + return; + } + + // + // Trigger Box ... + has = tb.trigger.IsValid(); + if (has) + { + UseBox(tb.trigger); + } + + // + // Order Block Box ... + has = tb.ob.IsValid(); + if (has) + { + UseBox(tb.ob); + } + + // + // Fair Value Gap ... + has = tb.fvg.IsValid(); + if (has) + { + UseBox(tb.fvg); + } + + // + // Following Liquidity ... + has = tb.fLiquidity.IsValid(); + if (has) + { + UseBox(tb.fLiquidity); + } + + // + // Reversal Liquidity ... + has = tb.rLiquidity.IsValid(); + if (has) + { + UseBox(tb.rLiquidity); + } + } + + /** + * Draw Exists Trigger Blocks ... + */ + void DrawTriggerBlocks(datetime to = NULL) + { + // + // Check Has Child of trigger Blocks ... + bool has = HasChild(triggerBlocks); + if (!has) + { + return; + } + + // + // Loop through Blocks ... + int count = ArraySize(triggerBlocks); + for (int i = 0; i < count; i++) + { + // + // Draw Indexed Trigger Block ... + DrawTriggerBlock( + triggerBlocks[i], + drawer.drawer, + mObjects, + to, + false // + ); + } + } + + /** + * Draw Pivot Zone ... + * + * @param box: XBoxZone instance Reference ... + */ + void DrawPivotZone(XBoxZone &box) + { + // + bool has = box.IsValid(); + if (!has) + { + return; + } + + // + XCBoxObject *iObj; + has = drawer + .drawer + .DrawBox( + box, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + } + + // + // Private ... + private: + // + // Props ... + string symbol; + string provider; + CArrayObj *mObjects; + ENUM_TIMEFRAMES period; + int maxAllowedCollection; // Max Allowed Collection Items ... + + // + // Initialize and Configure POI Detector and Drawer ... + void InitPOI() + { + // + // Initialize POI Detector ... + bool has = helper != NULL; + if (has) + { + // + detector = new XCXCATBEAPOIDetector(helper); + + // + // Configure ... + + // + detector.detectPeakPivots = true; + detector.detectValePivots = true; + + // + detector.detectMTBullishPivots = true; + detector.detectMTBearishPivots = true; + + // + detector.detectOBBullishPivots = true; + detector.detectOBBearishPivots = true; + } + + // + // Initialize POI Drawer ... + has = detector != NULL; + if (has) + { + // + drawer = new XCXCATBEAPOIDrawer(detector); + + // + // Configure ... + drawer.drawPeakPivots = true; + drawer.drawValePivots = true; + + // + XCATBPivotStyle iStyle; + + // + // Styling Peak Pivot ... + iStyle.width = 1; + iStyle.clr = clrMagenta; + iStyle.style = STYLE_SOLID; + + // + drawer.peakPivotStyle = iStyle; + + // + // Styling Vale Pivot ... + iStyle.width = 1; + iStyle.clr = clrAqua; + iStyle.style = STYLE_SOLID; + + // + drawer.valePivotStyle = iStyle; + + // + // Cleanup Resources ... + + // + iStyle.Clean(); + } + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 b/BKPS/14040626/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 new file mode 100644 index 0000000..0692390 --- /dev/null +++ b/BKPS/14040626/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 @@ -0,0 +1,2686 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCAYBEAPOIDetector ... +// Description: Class for XCATBEA POI Detector ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Class for XCATBEA POI Detector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" +#include "../../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +enum ENUM_XCATB_PIVOTS +{ + XCATB_NONE, // None + XCATB_PEAK, // Peak + XCATB_VALE, // Vale + XCATB_BULLISH_MT, // MTBull + XCATB_BEARISH_MT, // MTBear + XCATB_BULLISH_OB, // OBBull + XCATB_BEARISH_OB, // OBBear +}; + +// +bool IsValid(ENUM_XCATB_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XCATB_NONE; + + // + return result; +} +bool IsSpecifiedValid(ENUM_XCATB_PIVOTS value) +{ + return IsValid(value); +} + +// +string ToString(ENUM_XCATB_PIVOTS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} +string ToXString(ENUM_XCATB_PIVOTS value) +{ + return ToString(value); +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCATB_PIVOTS value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + switch (value) + { + // + case XCATB_VALE: + case XCATB_BULLISH_MT: + case XCATB_BULLISH_OB: + result = X_DIRECTION_BULLISH; + break; + + // + case XCATB_PEAK: + case XCATB_BEARISH_MT: + case XCATB_BEARISH_OB: + result = X_DIRECTION_BEARISH; + break; + } + + // + return result; +} + +// +string GetBoxType(ENUM_XCATB_PIVOTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case XCATB_VALE: + case XCATB_PEAK: + result = ToString(value); + break; + + // + case XCATB_BULLISH_MT: + case XCATB_BEARISH_MT: + result = "XMT"; + break; + + // + case XCATB_BULLISH_OB: + case XCATB_BEARISH_OB: + result = "XOB"; + break; + } + + // + return result; +} + +// +ENUM_XCATB_PIVOTS GetPivotType(XBoxZone &value) +{ + // + ENUM_XCATB_PIVOTS result = XCATB_NONE; + + // + bool has = value.IsValid(); + if (!has) + { + return result; + } + + // + bool isPeak = value.type == GetBoxType(XCATB_PEAK) && + value.dir == GetDirection(XCATB_PEAK); + bool isVale = value.type == GetBoxType(XCATB_VALE) && + value.dir == GetDirection(XCATB_VALE); + bool isBullishMT = value.type == GetBoxType(XCATB_BULLISH_MT) && + value.dir == GetDirection(XCATB_BULLISH_MT); + bool isBearishMT = value.type == GetBoxType(XCATB_BEARISH_MT) && + value.dir == GetDirection(XCATB_BEARISH_MT); + bool isBullishOB = value.type == GetBoxType(XCATB_BULLISH_OB) && + value.dir == GetDirection(XCATB_BULLISH_OB); + bool isBearishOB = value.type == GetBoxType(XCATB_BEARISH_OB) && + value.dir == GetDirection(XCATB_BEARISH_OB); + + // + if (isPeak) + { + result = XCATB_PEAK; + } + else if (isVale) + { + result = XCATB_VALE; + } + else if (isBullishMT) + { + result = XCATB_BULLISH_MT; + } + else if (isBearishMT) + { + result = XCATB_BEARISH_MT; + } + else if (isBullishOB) + { + result = XCATB_BULLISH_OB; + } + else if (isBearishOB) + { + result = XCATB_BEARISH_OB; + } + + // + return result; +} + +// +struct XCATBPivot +{ + // + // Props ... + datetime to; + double value; + string symbol; + datetime from; + double reserve; + ENUM_XCATB_PIVOTS type; + ENUM_TIMEFRAMES period; + + // + double values[]; + + // + // Constructor ... + XCATBPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCATB_NONE; + + // + SpecifiedClean(values); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + from < to && + value != 0 && + IsSpecifiedValid(to) && + IsSpecifiedValid(from) && + IsSpecifiedValid(type) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period); + + // + return result; + } + + /** + * Check a Model is Same as this or not ... + * + * @param pivot: XCATBPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XCATBPivot &pivot) + { + // + bool result = false; + + // + result = + IsValid() && + pivot.IsValid(); + if (!result) + { + return result; + } + + // + result = + to == pivot.to && + from == pivot.from && + type == pivot.type && + value == pivot.value && + symbol == pivot.symbol && + period == pivot.period; + + // + return result; + } + + /** + * Retrieve To Index ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int ToIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + to // + ); + + // + return result; + } + + /** + * Retrieve From Index ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int FromIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Retrieve Age of Pivot ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetAge( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + int toIDX = ToIndex(forPeriod); + int fromIDX = FromIndex(forPeriod); + + // + result = fromIDX - toIDX; + + // + return result; + } + + /** + * Converts Pivot to Box ... + * + * @param box: XBoxZone instance reference ... + * + * @return ( bool ) + */ + bool AsBox( + XBoxZone &box // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir = GetDirection(type); + + // + result = HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = + IsBullish(iDir) && + value < reserve; + + // + bool isBearish = + IsBearish(iDir) && + value > reserve; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + box.to = to; + box.dir = iDir; + box.from = from; + box.symbol = symbol; + box.period = period; + + // + string typeStr = GetBoxType(type); + box.type = typeStr; + + // + box.upper = + isBullish + ? reserve + : value; + box.lower = + isBullish + ? value + : reserve; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + // +}; + +// +// Implementations ... +class XCXCATBEAPOIDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + int maxAllowedPivots; // Max Allowed Holding Pibots ... + int pivotVerifications; // Pivots Verifications ... + int pivotDetectionLoopbac; // Pivots Detection Loopback ... + + // + // Breaked Pivots ... + XBoxZone invalidPivots[]; + + // + // Constructors ... + XCXCATBEAPOIDetector( + XCX121XCatbHelper *_helper // + ) + { + // + helper = _helper; + barAnalyser = new XCBarAnalyser(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCATBEAPOIDetector() + { + // + CleanPivots(); + + // + ZeroMemory(helper); + + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // COMMON ... + + // + maxAllowedPivots = 50; + pivotVerifications = 5; + pivotDetectionLoopbac = 100; + + // + // PV ... + + // + maxAllowedPVLifetime = 0; + selectRejectedPVPivots = false; + selectEngulfedPVPivots = false; + + // + detectPeakPivots = false; + detectValePivots = false; + + // + detectMTBullishPivots = false; + detectMTBearishPivots = false; + + // + detectOBBullishPivots = false; + detectOBBearishPivots = false; + } + + // + void Detect( + int barIndex = 0 // + ) + { + // + barIndex = NormalizeInt(barIndex, 0); + int loopback = pivotDetectionLoopbac; + loopback = NormalizeInt(loopback, 50); + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + newPeakPivotDetected = false; + newValePivotDetected = false; + newMTBullishPivotDetected = false; + newMTBearishPivotDetected = false; + newOBBullishPivotDetected = false; + newOBBearishPivotDetected = false; + + // + int index = barIndex; + int start = index; + int end = index + loopback; + while (start < end) + { + // + // Retrieve Conditions ... + X121XCatbConditions conditions; + has = helper.GetConditions( + conditions, + start, + 10 // + ); + if (!has) + { + conditions.Clean(); + continue; + } + + // + // Retrieve Bars ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + has = zBar.Init( + conditions.symbol, + conditions.period, + start // + ); + has = + has && + zBar.GetPreviousBar(cBar); + has = + has && + cBar.GetPreviousBar(pBar); + has = + has && + pBar.GetPreviousBar(p2Bar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + conditions.Clean(); + + // + continue; + } + + // + // Checking Pivots ... + + // + // PV ... + + // + // PEAK ... + if (detectPeakPivots) + { + // + newPeakPivotDetected = DetectPeakAndValePivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // VALE ... + if (detectValePivots) + { + // + newValePivotDetected = DetectPeakAndValePivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // MT ... + + // + // Bullish ... + if (detectMTBullishPivots) + { + // + newMTBullishPivotDetected = DetectMTPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectMTBearishPivots) + { + // + newMTBearishPivotDetected = DetectMTPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // OB ... + + // + // Bullish ... + if (detectOBBullishPivots) + { + // + newOBBullishPivotDetected = DetectOBPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectOBBearishPivots) + { + // + newOBBearishPivotDetected = DetectOBPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Others ... + + // + start++; + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + conditions.Clean(); + } + + // + SortPivots(); + } + + // + void Validate( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + // Implement Validation Senarios ... + + // + // PV ... + ValidatePeakValePivots( + unavailables, + barIndex // + ); + + // + // MT ... + ValidateMTPivots( + unavailables, + barIndex // + ); + + // + // OB ... + ValidateOBPivots( + unavailables, + barIndex // + ); + + // + SortPivots(); + } + + // + void CleanPivots() + { + // + Clean(invalidPivots); + + // + peakPivot.Clean(); + valePivot.Clean(); + + // + Clean(peakPivots); + Clean(valePivots); + + // + Clean(mtBullishPivots); + Clean(mtBearishPivots); + + // + Clean(obBullishPivots); + Clean(obBearishPivots); + } + + // + // Pivots ... + + // + // INVALID Pivots ... + + // + bool HasInvalidPivots() + { + return HasChild(invalidPivots); + } + + // + int CountInvalidPivots() + { + return ArraySize(invalidPivots); + } + + // + // PV ... + + // + int maxAllowedPVLifetime; // Max Allowed PV Life ... + bool selectRejectedPVPivots; // Select Rejected PV Pivots ... + bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ... + + // + bool DetectPeakAndValePivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + X121XCatbConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectValePivots + : detectPeakPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // PEAK Golden ... + double zPeakGolden = conditions.peakGoldenBuffer[zIDX]; + double cPeakGolden = conditions.peakGoldenBuffer[cIDX]; + double pPeakGolden = conditions.peakGoldenBuffer[pIDX]; + double p2PeakGolden = conditions.peakGoldenBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // VALE Golden ... + double zValeGolden = conditions.valeGoldenBuffer[zIDX]; + double cValeGolden = conditions.valeGoldenBuffer[cIDX]; + double pValeGolden = conditions.valeGoldenBuffer[pIDX]; + double p2ValeGolden = conditions.valeGoldenBuffer[p2IDX]; + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Rejected ... + bool isCBarRejected = barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + + // + bool isCBarBullishRejected = + forBullish && + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + forBearish && + isCBarRejected && + IsBearish(cBarDir); + + // + bool isPBarRejected = barAnalyser + .IsRejected( + pBar, + cBarDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + bool isPBarBullishRejected = + forBullish && + isPBarRejected && + IsBullish(cBarDir); + bool isPBarBearishRejected = + forBearish && + isPBarRejected && + IsBearish(cBarDir); + + // + bool isBarBullishRejected = + forBullish && + (isCBarBullishRejected || + isPBarBullishRejected); + + // + bool isBarBearishRejected = + forBearish && + (isCBarBearishRejected || + isPBarBearishRejected); + + // + // Engulfed ... + bool isCBarEngulfed = barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + forBullish && + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + forBearish && + isCBarEngulfed && + IsBearish(cBarDir); + + // + bool isPBarEngulfed = barAnalyser + .IsEngulfed( + pBar, + cBarDir // + ); + bool isPBarBullishEngulfed = + forBullish && + isPBarEngulfed && + IsBullish(cBarDir); + bool isPBarBearishEngulfed = + forBearish && + isPBarEngulfed && + IsBearish(cBarDir); + + // + bool isBarBullishEngulfed = + forBullish && + (isCBarBullishEngulfed || + isPBarBullishEngulfed); + + // + bool isBarBearishEngulfed = + forBearish && + (isCBarBearishEngulfed || + isPBarBearishEngulfed); + + // + // Prepare Conditinal Conditions ... + + // + // PEAK ... + + // + bool isPeakSameLast = cPeak == pPeak; + bool isPeakSameLastPrev = pPeak == p2Peak; + + // + bool isPeakSwitchedToSameLast = isPeakSameLast && + !isPeakSameLastPrev; + bool isPeakFinishedFromSameLast = !isPeakSameLast && + isPeakSameLastPrev; + + // + // VALE ... + + // + bool isValeSameLast = cVale == pVale; + bool isValeSameLastPrev = pVale == p2Vale; + + // + bool isValeSwitchedToSameLast = isValeSameLast && + !isValeSameLastPrev; + bool isValeFinishedFromSameLast = !isValeSameLast && + isValeSameLastPrev; + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = + // + forBullish + ? isValeFinishedFromSameLast + : isPeakFinishedFromSameLast + // + ; + + // + bool hasContinuationCondition = + // + forBullish + ? isValeSameLast + : isPeakSameLast + // + ; + + // + bool hasEndCondition = + // + forBullish + ? isValeSwitchedToSameLast + : isPeakSwitchedToSameLast + // + ; + + // + // Apply Validations ... + if (hasEndCondition) + { + // + bool hasSelectionType = selectRejectedPVPivots || + selectEngulfedPVPivots; + + // + bool isPVRejected = + forBullish + ? (isBarBullishRejected && + selectRejectedPVPivots) + : (isBarBearishRejected && + selectRejectedPVPivots); + + // + bool isPVEngulfed = + forBullish + ? (isBarBullishEngulfed && + selectEngulfedPVPivots) + : (isBarBearishEngulfed && + selectEngulfedPVPivots); + + // + bool isBarPassed = + !hasSelectionType + ? true + : isPVRejected || + isPVEngulfed; + + // + hasEndCondition = + isBarPassed && + hasEndCondition; + if (!hasEndCondition) + { + // + // VALE ... + if (forBullish) + { + valePivot.Clean(); + } + + // + // PEAK ... + if (forBearish) + { + peakPivot.Clean(); + } + } + } + + // + // + // + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + // VALE ... + if (forBullish) + { + // + valePivot.Clean(); + + // + valePivot.type = XCATB_VALE; + valePivot.symbol = symbol; + valePivot.period = period; + + // + valePivot.to = pBar.time; + valePivot.from = pBar.time; + valePivot.value = pVale; + valePivot.reserve = pValeGolden; + } + + // + // PEAK ... + if (forBearish) + { + // + peakPivot.Clean(); + + // + peakPivot.type = XCATB_PEAK; + peakPivot.symbol = symbol; + peakPivot.period = period; + + // + peakPivot.to = pBar.time; + peakPivot.from = pBar.time; + peakPivot.value = pPeak; + peakPivot.reserve = pPeakGolden; + } + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + // VALE ... + if (forBullish) + { + // + valePivot.from = pBar.time; + + // + valePivot.reserve = + valePivot.reserve == 0 + ? pValeGolden + : MathMin(valePivot.reserve, pValeGolden); + } + + // + // PEAK ... + if (forBearish) + { + // + peakPivot.from = pBar.time; + + // + peakPivot.reserve = + peakPivot.reserve == 0 + ? pPeakGolden + : MathMax(peakPivot.reserve, pPeakGolden); + } + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // VALE ... + if (forBullish) + { + // + result = + valePivot.IsValid() && + valePivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = valePivot.AsBox(iBox); + if (result) + { + // + newValePivotDetected = AddBox( + iBox, + valePivots // + ); + } + + // + iBox.Clean(); + } + + // + valePivot.Clean(); + } + + // + // PEAK ... + if (forBearish) + { + // + result = + peakPivot.IsValid() && + peakPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = peakPivot.AsBox(iBox); + if (result) + { + // + newPeakPivotDetected = AddBox( + iBox, + peakPivots // + ); + } + + // + iBox.Clean(); + } + + // + peakPivot.Clean(); + } + } + + // + return result; + } + + // + void ValidatePeakValePivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedPVLifetime > 0; + + // + // PEAK ... + has = HasPeakPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + peakPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + peakPivots, + maxAllowedPVLifetime, + barIndex // + ); + } + } + + // + // VALE ... + has = HasValePivots(); + if (has) + { + // + ApplyValidationOnBoxes( + valePivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + valePivots, + maxAllowedPVLifetime, + barIndex // + ); + } + } + } + + // + // PEAK ... + + // + XCATBPivot peakPivot; + bool detectPeakPivots; + XBoxZone peakPivots[]; + bool newPeakPivotDetected; + + // + bool HasPeakPivots() + { + return HasChild(peakPivots); + } + + // + int CountPeakPivots() + { + return ArraySize(peakPivots); + } + + // + int FillPeakPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasPeakPivots()) + { + return result; + } + + // + int count = CountPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = peakPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // VALE ... + + // + XCATBPivot valePivot; + bool detectValePivots; + XBoxZone valePivots[]; + bool newValePivotDetected; + + // + bool HasValePivots() + { + return HasChild(valePivots); + } + + // + int CountValePivots() + { + return ArraySize(valePivots); + } + + // + int FillValePivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasValePivots()) + { + return result; + } + + // + int count = CountValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = valePivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // MITIGATIONBLOCK ... + + // + int maxAllowedMTLifetime; // Max Allowed MT Life ... + + // + bool DetectMTPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + X121XCatbConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectMTBullishPivots + : detectMTBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Rejected ... + bool isCBarRejected = barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + + // + bool isCBarBullishRejected = + forBullish && + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + forBearish && + isCBarRejected && + IsBearish(cBarDir); + + // + // Prepare Conditinal Conditions ... + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasEndCondition = + // + forBullish + ? isCBarBullishRejected + : isCBarBearishRejected + // + ; + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + XBoxZone iPivot; + iPivot.to = zBar.time; + iPivot.from = cBar.time; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + // Bullish ... + if (forBullish) + { + // + iPivot.lower = cBar.low; + iPivot.upper = cBar.GetDown(); + iPivot.dir = X_DIRECTION_BULLISH; + iPivot.type = GetBoxType(XCATB_BULLISH_MT); + + // + result = iPivot.IsValid(); + if (result) + { + // + newMTBullishPivotDetected = AddBox( + iPivot, + mtBullishPivots // + ); + } + } + + // + // Bearish ... + if (forBearish) + { + // + iPivot.upper = cBar.high; + iPivot.lower = cBar.GetUp(); + iPivot.dir = X_DIRECTION_BEARISH; + iPivot.type = GetBoxType(XCATB_BEARISH_MT); + + // + result = iPivot.IsValid(); + if (result) + { + // + newMTBearishPivotDetected = AddBox( + iPivot, + mtBearishPivots // + ); + } + } + } + + // + return result; + } + + // + void ValidateMTPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedMTLifetime > 0; + + // + // Bullish ... + has = HasMTBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + mtBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + mtBullishPivots, + maxAllowedMTLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasMTBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + mtBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + mtBearishPivots, + maxAllowedMTLifetime, + barIndex // + ); + } + } + } + + // + // Bullish ... + XBoxZone mtBullishPivots[]; + bool detectMTBullishPivots; + bool newMTBullishPivotDetected; + + // + bool HasMTBullishPivots() + { + return HasChild(mtBullishPivots); + } + + // + int CountMTBullishPivots() + { + return ArraySize(mtBullishPivots); + } + + // + int FillMTBullishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasMTBullishPivots()) + { + return result; + } + + // + int count = CountMTBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = mtBullishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Bearish ... + XBoxZone mtBearishPivots[]; + bool detectMTBearishPivots; + bool newMTBearishPivotDetected; + + // + bool HasMTBearishPivots() + { + return HasChild(mtBearishPivots); + } + + // + int CountMTBearishPivots() + { + return ArraySize(mtBearishPivots); + } + + // + int FillMTBearishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasMTBearishPivots()) + { + return result; + } + + // + int count = CountMTBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = mtBearishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // ORDERBLOCK ... + + // + int maxAllowedOBLifetime; // Max Allowed MT Life ... + + // + bool DetectOBPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + X121XCatbConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectOBBullishPivots + : detectOBBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + XBoxZone iPivot; + + // + // Detecting Bar Conditions ... + + // + + // + // OB ... + bool isOB = barAnalyser + .IsOB( + cBar, + iPivot, + false, + false // + ); + + // + bool isBullishOB = + isOB && + iPivot.IsBullish(); + bool isBearishOB = + isOB && + iPivot.IsBearish(); + + // + // Prepare Conditinal Conditions ... + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasEndCondition = + // + forBullish + ? isBullishOB + : isBearishOB + // + ; + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // Bullish ... + if (forBullish) + { + // + iPivot.type = GetBoxType(XCATB_BULLISH_OB); + + // + result = iPivot.IsValid(); + if (result) + { + // + newOBBullishPivotDetected = AddBox( + iPivot, + obBullishPivots // + ); + } + } + + // + // Bearish ... + if (forBearish) + { + // + iPivot.type = GetBoxType(XCATB_BEARISH_OB); + + // + result = iPivot.IsValid(); + if (result) + { + // + newOBBearishPivotDetected = AddBox( + iPivot, + obBearishPivots // + ); + } + } + } + + // + return result; + } + + // + void ValidateOBPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedOBLifetime > 0; + + // + // Bullish ... + has = HasOBBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + obBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + obBullishPivots, + maxAllowedOBLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasOBBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + obBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + obBearishPivots, + maxAllowedOBLifetime, + barIndex // + ); + } + } + } + + // + // Bullish ... + XBoxZone obBullishPivots[]; + bool detectOBBullishPivots; + bool newOBBullishPivotDetected; + + // + bool HasOBBullishPivots() + { + return HasChild(obBullishPivots); + } + + // + int CountOBBullishPivots() + { + return ArraySize(obBullishPivots); + } + + // + int FillOBBullishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasOBBullishPivots()) + { + return result; + } + + // + int count = CountOBBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = obBullishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Bearish ... + XBoxZone obBearishPivots[]; + bool detectOBBearishPivots; + bool newOBBearishPivotDetected; + + // + bool HasOBBearishPivots() + { + return HasChild(obBearishPivots); + } + + // + int CountOBBearishPivots() + { + return ArraySize(obBearishPivots); + } + + // + int FillOBBearishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasOBBearishPivots()) + { + return result; + } + + // + int count = CountOBBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = obBearishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Protected ... + protected: + // + // Props ... + + // + bool AddBox( + XBoxZone &box, + XBoxZone &boxes[] // + ) + { + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = FindIndex( + idx, + box, + boxes // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + int before = ArraySize(boxes); + + // + AddRef( + box, + boxes // + ); + + // + int after = ArraySize(boxes); + + // + result = after > before; + + // + return result; + } + + // + bool ValidateBox( + XBoxZone &box, + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Bar Index ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Ceck Input Box is Valid ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + // Check Input Box is Available ... + bool canCheckUnAvailableBoxes = HasChild(unavailables); + if (canCheckUnAvailableBoxes) + { + // + int idx = -1; + bool isUnAvailable = FindIndex( + idx, + box, + unavailables // + ); + result = !isUnAvailable; + if (!result) + { + return result; + } + } + + // + // Check Input Box is Breaked or not ... + + // + // Check Bar Index must after Box To Index ... + int toIDX = box.ToIndex(); + int fromIDX = box.FromIndex(); + result = toIDX > barIndex && + fromIDX > barIndex && + fromIDX > toIDX; + if (!result) + { + return result; + } + + // + // Detect Box Applied Boundary Price ... + // For Checking Break of Box ... + bool isBullish = box.IsBullish(); + double boundary = + isBullish + ? box.lower + : box.upper; + + // + // for validating Box Break we have to wait At Least 3 Bars Close + // out of Box Boundary ... + int barsLength = 3; + + // + // Calculate Start Checking Bar Index ... + int startCheckBreaktionBarIndex = toIDX - barsLength; + bool isBarIndexValid = startCheckBreaktionBarIndex > 0 && + barIndex < startCheckBreaktionBarIndex; + result = isBarIndexValid; + if (!result) + { + // + // Assume Box is Valid if Bar Index not Valid for Checking ... + result = true; + return result; + } + + // + // Try to Check Box Validation if Everything is OK ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + bool isValid = false; + bool isBreaked = false; + for (int i = barIndex; i < startCheckBreaktionBarIndex; i++) + { + // + // Initialize Bars ... + isValid = cBar.Init( + box.symbol, + box.period, + i + 1 // + ); + isValid = + result && + cBar.GetPreviousBar(pBar); + isValid = + result && + pBar.GetPreviousBar(p2Bar); + if (!isValid) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + result = false; + + // + break; + } + + // + // Preparing Conditions ... + + // + bool isBullishBreaked = + isBullish && + cBar.close < boundary && + pBar.close < boundary && + p2Bar.close < boundary; + + // + bool isBearishBreaked = + !isBullish && + cBar.close > boundary && + pBar.close > boundary && + p2Bar.close > boundary; + + // + // Calculate Result ... + isBreaked = isBullishBreaked || + isBearishBreaked; + if (isBreaked) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + result = false; + + // + break; + } + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + } + + // + result = isValid && + !isBreaked; + if (!result) + { + // + int idx = -1; + bool isExists = FindIndex( + idx, + box, + invalidPivots // + ); + if (!isExists) + { + // + AddRef( + box, + invalidPivots // + ); + } + } + + // + // Cleanup Resource ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + void SortPivots() + { + // + bool has = false; + + // + // Invalid Pivots ... + has = HasInvalidPivots(); + if (has) + { + SortBoxes(invalidPivots); + } + + // + // PV ... + + // + // PEAK ... + has = HasPeakPivots(); + if (has) + { + SortBoxes(peakPivots); + } + + // + // VALE ... + has = HasValePivots(); + if (has) + { + SortBoxes(valePivots); + } + + // + // MT Bullish ... + has = HasMTBullishPivots(); + if (has) + { + SortBoxes(mtBullishPivots); + } + + // + // MT Bearish ... + has = HasMTBearishPivots(); + if (has) + { + SortBoxes(mtBearishPivots); + } + + // + // OB Bullish ... + has = HasOBBullishPivots(); + if (has) + { + SortBoxes(obBullishPivots); + } + + // + // OB Bearish ... + has = HasOBBearishPivots(); + if (has) + { + SortBoxes(obBearishPivots); + } + } + + // + void ApplyValidationOnBoxes( + XBoxZone &items[], + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = ValidateBox( + iBox, + unavailables, + barIndex // + ); + if (has) + { + // + AddRef( + iBox, + items // + ); + } + + // + iBox.Clean(); + // + } + + // + Clean(tmp); + } + + // + void ApplyLifeTimeValidationOnBoxes( + XBoxZone &items[], + int maxAllowedAge = 0, + int barIndex = 0 // + ) + { + // + bool has = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + has = + maxAllowedAge > 0 && + HasChild(items); + if (!has) + { + return; + } + + // + datetime cTime = GetBarTime( + helper.GetSymbol(), + helper.GetPeriod(), + barIndex // + ); + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + datetime defTo = iBox.to; + iBox.to = cTime; + + // + int iAge = iBox.GetAge(); + has = iAge <= maxAllowedAge; + iBox.to = defTo; + if (has) + { + // + AddRef( + iBox, + items // + ); + } + else + { + // + int idx = -1; + bool isExists = FindIndex( + idx, + iBox, + invalidPivots // + ); + if (!isExists) + { + // + AddRef( + iBox, + invalidPivots // + ); + } + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + } + + // + // Prrivate ... + private: + // + // Props ... + + // + XCX121XCatbHelper *helper; + XCBarAnalyser *barAnalyser; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 b/BKPS/14040626/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..29c27aa --- /dev/null +++ b/BKPS/14040626/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 @@ -0,0 +1,1193 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCATBEAPOIDrawer ... +// Description: XCATBEA POI Drawer Class +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCATBEA POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Classes/xcatbea.x-poi.detector.class.mq5" + +// +// Definitions ... +struct XCATBPivotStyle +{ + // + // Properties ... + int width; + color clr; + ENUM_LINE_STYLE style; + + // + // Constructor ... + XCATBPivotStyle() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup Model ... + void Clean() + { + // + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + ZeroMemory(this); + } + + // + // Default Props ... + void Default() + { + // + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + } +}; + +// +// Implementations ... +class XCXCATBEAPOIDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCPOIDrawer *drawer; + + // + // Drawers ... + bool drawPeakPivots; + bool drawValePivots; + bool drawMTBullishPivots; + bool drawMTBearishPivots; + bool drawOBBullishPivots; + bool drawOBBearishPivots; + + // + // Styling ... + + // + XCATBPivotStyle defaultBullishStyle; + XCATBPivotStyle defaultBearishStyle; + + // + XCATBPivotStyle peakPivotStyle; + XCATBPivotStyle valePivotStyle; + + // + XCATBPivotStyle mtBullishPivotStyle; + XCATBPivotStyle mtBearishPivotStyle; + + // + XCATBPivotStyle obBullishPivotStyle; + XCATBPivotStyle obBearishPivotStyle; + + // + // Constructors ... + XCXCATBEAPOIDrawer( + XCXCATBEAPOIDetector *_detector // + ) + { + // + detector = _detector; + drawer = new XCPOIDrawer(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCATBEAPOIDrawer() + { + // + Clear(); + + // + delete drawer; + ZeroMemory(drawer); + + // + ZeroMemory(detector); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // Drawing ... + drawPeakPivots = false; + drawValePivots = false; + drawMTBullishPivots = false; + drawMTBearishPivots = false; + drawOBBullishPivots = false; + drawOBBearishPivots = false; + + // + // Styling ... + + // + // Bullish ... + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrLime; + defaultBullishStyle.style = STYLE_SOLID; + + // + // Bearish ... + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrRed; + defaultBearishStyle.style = STYLE_SOLID; + + // + // Pivots ... + + // + // PV ... + peakPivotStyle = defaultBearishStyle; + valePivotStyle = defaultBullishStyle; + + // + // MT ... + mtBullishPivotStyle = defaultBullishStyle; + mtBearishPivotStyle = defaultBearishStyle; + + // + // OB ... + obBullishPivotStyle = defaultBullishStyle; + obBearishPivotStyle = defaultBearishStyle; + } + + // + void Draw(datetime to = NULL) + { + // + // PV ... + DrawPeakPivots(to); + DrawValePivots(to); + + // + // MT ... + DrawMTBullishPivots(to); + DrawMTBearishPivots(to); + + // + // OB ... + DrawOBBullishPivots(to); + DrawOBBearishPivots(to); + } + + // + void DrawPivot( + XBoxZone &pivot, + datetime to = NULL // + ) + { + // + DrawBox( + pivot, + to, + false, + false // + ); + } + + // + void DrawBox( + XBoxZone &box, + datetime to = NULL, + bool drawMiddle = false, + bool ignoreType = false // + ) + { + // + bool has = box.IsValid(); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + box.to = to; + } + + // + // Draw Box as POI ... + if (!ignoreType) + { + // + // Detect Pivot Type ... + ENUM_XCATB_PIVOTS iType = GetPivotType(box); + has = IsValid(iType); + if (!has) + { + return; + } + + // + switch (iType) + { + // + case XCATB_PEAK: + // + DrawPeakPivot( + box, + to // + ); + break; + + // + case XCATB_VALE: + // + DrawValePivot( + box, + to // + ); + break; + + // + case XCATB_BULLISH_MT: + // + DrawMTBullishPivot( + box, + to // + ); + break; + + // + case XCATB_BEARISH_MT: + // + DrawMTBearishPivot( + box, + to // + ); + break; + + // + case XCATB_BULLISH_OB: + // + DrawOBBullishPivot( + box, + to // + ); + break; + + // + case XCATB_BEARISH_OB: + // + DrawOBBearishPivot( + box, + to // + ); + break; + } + } + // + // Draw Regular Box ... + else + { + // + // Select Styling Config ... + XCATBPivotStyle style; + + // + if (box.IsBullish()) + { + style = defaultBullishStyle; + } + else + { + style = defaultBearishStyle; + } + + // + // Draw Box itself ... + XCBoxObject *iBoxObj; + has = drawer.DrawBox( + box, + iBoxObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iBoxObj, + style // + ); + + // + // Store Object ... + mObjects.Add(iBoxObj); + } + + // + // Draw Box Middle Range ... + if (drawMiddle) + { + // + double middle = box.GetMid(); + string middleName = box.GetMiddleTag(); + + // + CChartObjectTrend *iMidObj; + iMidObj = new CChartObjectTrend(); + has = iMidObj.Create( + drawer.ChartIdentification(), + middleName, + drawer.SubWindowIdentification(), + box.from, + middle, + box.to, + middle // + ); + if (has) + { + // + // Styling Object ... + iMidObj.Color(style.clr); + iMidObj.Width(style.width); + iMidObj.Style(style.style); + + // + // Store Object ... + mObjects.Add(iMidObj); + } + } + + // + style.Clean(); + } + } + + // + void DrawBoxes( + XBoxZone &boxes[], + datetime to = NULL, + bool drawMiddle = false, + bool ignoreType = false // + ) + { + // + bool has = HasChild(boxes); + if (!has) + { + return; + } + + // + int count = ArraySize(boxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + // Detect Pivot Type ... + DrawBox( + iBox, + to, + drawMiddle, + ignoreType // + ); + + // + iBox.Clean(); + } + } + + // + void Clear() + { + // + // Cleanup Models ... + defaultBullishStyle.Clean(); + defaultBearishStyle.Clean(); + + // + // Cleanup Styles ... + peakPivotStyle.Clean(); + valePivotStyle.Clean(); + mtBullishPivotStyle.Clean(); + mtBearishPivotStyle.Clean(); + obBullishPivotStyle.Clean(); + obBearishPivotStyle.Clean(); + + // + // Cleanup Pivot Objects Holder ... + mObjects.Clear(); + mPeakPivotObjects.Clear(); + mValePivotObjects.Clear(); + mMTBullishPivotObjects.Clear(); + mMTBearishPivotObjects.Clear(); + mOBBullishPivotObjects.Clear(); + mOBBearishPivotObjects.Clear(); + } + + // + // Collection Drawers ... + + // + void DrawPeakPivots(datetime to = NULL) + { + // + bool has = drawPeakPivots; + if (!has) + { + return; + } + + // + has = detector.HasPeakPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.peakPivots[i]; + + // + DrawPeakPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawValePivots(datetime to = NULL) + { + // + bool has = drawValePivots; + if (!has) + { + return; + } + + // + has = detector.HasValePivots(); + if (!has) + { + return; + } + + // + int count = detector.CountValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.valePivots[i]; + + // + DrawValePivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawMTBullishPivots(datetime to = NULL) + { + // + bool has = drawMTBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasMTBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountMTBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.mtBullishPivots[i]; + + // + DrawMTBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawMTBearishPivots(datetime to = NULL) + { + // + bool has = drawMTBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasMTBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountMTBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.mtBearishPivots[i]; + + // + DrawMTBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawOBBullishPivots(datetime to = NULL) + { + // + bool has = drawOBBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasOBBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountOBBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.obBullishPivots[i]; + + // + DrawOBBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawOBBearishPivots(datetime to = NULL) + { + // + bool has = drawOBBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasOBBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountOBBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.obBearishPivots[i]; + + // + DrawOBBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + // One Item Drawers ... + + // + void DrawPeakPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawPeakPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_PEAK) && + item.dir == GetDirection(XCATB_PEAK); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + peakPivotStyle // + ); + + // + // Store Object ... + mPeakPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawValePivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawValePivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_VALE) && + item.dir == GetDirection(XCATB_VALE); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + valePivotStyle // + ); + + // + // Store Object ... + mValePivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawMTBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawMTBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BULLISH_MT) && + item.dir == GetDirection(XCATB_BULLISH_MT); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + mtBullishPivotStyle // + ); + + // + // Store Object ... + mMTBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawMTBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawMTBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BEARISH_MT) && + item.dir == GetDirection(XCATB_BEARISH_MT); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + mtBearishPivotStyle // + ); + + // + // Store Object ... + mMTBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawOBBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawOBBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BULLISH_OB) && + item.dir == GetDirection(XCATB_BULLISH_OB); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + obBullishPivotStyle // + ); + + // + // Store Object ... + mOBBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawOBBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawOBBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BEARISH_OB) && + item.dir == GetDirection(XCATB_BEARISH_OB); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + obBearishPivotStyle // + ); + + // + // Store Object ... + mOBBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Styling Tools ... + + /** + * Apply Default Bullish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyBullishStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, defaultBullishStyle); + } + + /** + * Apply Default Bearish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyBearishStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, defaultBearishStyle); + } + + /** + * Apply Peak Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyPeakPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, peakPivotStyle); + } + + /** + * Apply Vale Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyValePivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, valePivotStyle); + } + + /** + * Apply MT Bullish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyMTBullishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, mtBullishPivotStyle); + } + + /** + * Apply MT Bearish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyMTBearishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, mtBearishPivotStyle); + } + + /** + * Apply OB Bullish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyOBBullishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, obBullishPivotStyle); + } + + /** + * Apply OB Bearish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyOBBearishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, obBearishPivotStyle); + } + + /** + * Apply Pivot Style to Specified Object ... + */ + void ApplyPivotStyle( + XCBoxObject *&object, + XCATBPivotStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.BoxColor(style.clr); + object.BoxWidth(style.width); + object.BoxStyle(style.style); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + XCXCATBEAPOIDetector *detector; + + // + CArrayObj mObjects; + + // + CArrayObj mPeakPivotObjects; + CArrayObj mValePivotObjects; + + // + CArrayObj mMTBullishPivotObjects; + CArrayObj mMTBearishPivotObjects; + + // + CArrayObj mOBBullishPivotObjects; + CArrayObj mOBBearishPivotObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 b/BKPS/14040626/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 new file mode 100644 index 0000000..0d093f1 --- /dev/null +++ b/BKPS/14040626/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 @@ -0,0 +1,3798 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCXCATBEATradeManager +// Description: provides all Requirements for Managing Trades ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-alert.class.mq5" +#include "../../Classes/x-saherelm.x-data.collector.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/xcatbea.lib.mq5" +#include "../Libraries/xcatbea.signaller.lib.mq5" + +// +// Definitions ... + +// +enum ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD +{ + XCATBEA_TRADE_RESTRICATION_NONE, // None + XCATBEA_TRADE_RESTRICATION_HOURLY, // Per Hour + XCATBEA_TRADE_RESTRICATION_DAILY, // Per Day + XCATBEA_TRADE_RESTRICATION_WEEKLY, // Per Week + XCATBEA_TRADE_RESTRICATION_MONTHLY, // Per Month +}; + +// +string ToString(ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} +string ToXString(ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD value) +{ + return ToString(value); +} + +// +enum ENUM_XCATBEA_TRADE_FINALIZATION +{ + XCATBEA_TRADE_FINAL_NONE, // None + XCATBEA_TRADE_FINAL_TP, // TP + XCATBEA_TRADE_FINAL_SL, // SL + XCATBEA_TRADE_FINAL_CLOSE_IN_PROFIT, // Profit + XCATBEA_TRADE_FINAL_CLOSE_IN_LOSE, // Lost +}; + +// +string ToString(ENUM_XCATBEA_TRADE_FINALIZATION value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} +string ToXString(ENUM_XCATBEA_TRADE_FINALIZATION value) +{ + return ToString(value); +} + +// +// Position Selecting ... +enum ENUM_XCATBEA_POSITION_SELECT_TYPES +{ + XCATBEA_POSITION_SELECT_NONE = 0, // None + XCATBEA_POSITION_SELECT_ALL = 1, // All + XCATBEA_POSITION_SELECT_IN_PROFITS = 2, // In Profit Positions + XCATBEA_POSITION_SELECT_IN_DRAWDOWNS = 3, // In Drawdown Positions + XCATBEA_POSITION_SELECT_OLDEST = 4, // Oldest Position + XCATBEA_POSITION_SELECT_YOUNGEST = 5, // Youngest Position + XCATBEA_POSITION_SELECT_IN_PROFITS_OLDEST = 6, // In Profit Positions Oldest one + XCATBEA_POSITION_SELECT_IN_PROFITS_YOUNGEST = 7, // In Profit Positions Youngest one + XCATBEA_POSITION_SELECT_IN_PROFITS_MIN = 8, // Minimum Profitable Position + XCATBEA_POSITION_SELECT_IN_PROFITS_MAX = 9, // Maximum Profitable Position + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_OLDEST = 10, // In Drawdown Positions Oldest one + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_YOUNGEST = 11, // In Drawdown Positions Youngest one + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MIN = 12, // Minimum in Drawdown Position + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MAX = 13, // Maximum in Drawdown Position + XCATBEA_POSITION_SELECT_SAMES = 14, // Same Type Positions + XCATBEA_POSITION_SELECT_SAMES_OLDEST = 15, // Same Type Positions Oldest one + XCATBEA_POSITION_SELECT_SAMES_YOUNGEST = 16, // Same Type Positions Youngest one + XCATBEA_POSITION_SELECT_OPPOSITS = 17, // Opposit Type Positions + XCATBEA_POSITION_SELECT_OPPOSIT_OLDEST = 18, // Opposit Type Positions Oldest one + XCATBEA_POSITION_SELECT_OPPOSIT_YOUNGEST = 19, // Opposit Type Positions Youngest one + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS = 20, // Same Type In Profit Positions + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_OLDEST = 21, // Same Type In Profit Positions Oldest one + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_YOUNGEST = 22, // Same Type In Profit Positions Youngest one + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MIN = 23, // Minimum Profitable of Same Type Positions + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MAX = 24, // Maximum Profitable of Same Type Positions + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS = 25, // Opposit Type In Profit Positions + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST = 26, // Opposit Type In Profit Positions Oldest one + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST = 27, // Opposit Type In Profit Positions Youngest one + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MIN = 28, // Minimum Profitable of Opposit Type Positions + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MAX = 29, // Maximum Profitable of Opposit Type Positions + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWNS = 30, // Same Type In Deawdown Positions + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST = 31, // Same Type In Deawdown Positions Oldest one + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST = 32, // Same Type In Deawdown Positions Youngest one + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MIN = 33, // Minimum In Drawdown of Same Type Positions + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MAX = 34, // Maximum In Drawdown of Same Type Positions + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWNS = 35, // Opposit Type In Deawdown Positions + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST = 36, // Opposit Type In Deawdown Positions Oldest one + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST = 37, // Opposit Type In Deawdown Positions Youngest one + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN = 38, // Minimum In Drawdown of Opposit Type Positions + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX = 39, // Maximum In Drawdown of Opposit Type Positions +}; + +// +bool IsValid(ENUM_XCATBEA_POSITION_SELECT_TYPES value) +{ + return value != XCATBEA_POSITION_SELECT_NONE; +} +bool IsSpecifiedValid(ENUM_XCATBEA_POSITION_SELECT_TYPES value) +{ + return IsValid(value); +} + +// +string ToString(ENUM_XCATBEA_POSITION_SELECT_TYPES value) +{ + return EnumToString(value); +} +string ToXString(ENUM_XCATBEA_POSITION_SELECT_TYPES value) +{ + return ToString(value); +} + +/** + * Select Specified Position's Related Position(s) + * for Protecting ... + * + * @param selecteds: XPosition instance reference Collection, for Holding Selected Positions ... + * @param positions: XPosition instance reference Collection, All available source Positions ... + * @param forType: ENUM_X_POSITION_TYPES member, Spcified Position Type to Select for it ... + * @param selectType: ENUM_XCATBEA_POSITION_SELECT_TYPES member, Specified Positions Selecting Senario ... + * + * @return ( bool ) + */ +bool SelectPosition( + XPosition &selecteds[], + XPosition &positions[], + ENUM_X_POSITION_TYPES forType, + ENUM_XCATBEA_POSITION_SELECT_TYPES selectType // +) +{ + // + bool result = false; + + // + // Normalize Args ... + Clean(selecteds); + + // + // Validate Args ... + result = + IsValid(forType) && + HasChild(positions) && + IsValid(selectType); + if (!result) + { + return result; + } + + // + // Extract Separate Type of Positions ... + + // + int idx = -1; + bool has = false; + XPosition iPosition; + + // + bool isLong = IsLong(forType); + bool isShort = IsShort(forType); + int count = ArraySize(positions); + + // + XPosition samePositions[]; + XPosition oppositPositions[]; + XPosition inProfitPositions[]; + XPosition inDrawdownPositions[]; + XPosition sameInProfitPositions[]; + XPosition sameInDrawdownPositions[]; + XPosition oppositInProfitPositions[]; + XPosition oppositInDrawdownPositions[]; + + // + for (int i = 0; i < count; i++) + { + // + // Select Indexed Position ... + iPosition = positions[i]; + + // + bool isIPosLong = IsLong(iPosition.type); + bool isIPosShort = IsShort(iPosition.type); + + // + // Select if Same Type ... + bool isSame = + (isLong && isIPosLong) || + (isShort && isIPosShort); + if (isSame) + { + // + AddRef( + iPosition, + samePositions // + ); + } + + // + // Select if Opposit Type ... + bool isOpposit = + (isLong && isIPosShort) || + (isShort && isIPosLong); + if (isOpposit) + { + // + AddRef( + iPosition, + oppositPositions // + ); + } + + // + iPosition.Clean(); + } + + // + // Filling Other Requirement Collections ... + + // + ExtractInProfitPositions( + positions, + inProfitPositions // + ); + + // + ExtractInProfitPositions( + samePositions, + sameInProfitPositions // + ); + + // + ExtractInProfitPositions( + oppositPositions, + oppositInProfitPositions // + ); + + // + ExtractInDrawdownPositions( + positions, + inDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + samePositions, + sameInDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + oppositPositions, + oppositInDrawdownPositions // + ); + + // + // Implement Selection Senario ... + switch (selectType) + { + // + case XCATBEA_POSITION_SELECT_ALL: + // + Copy( + positions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS: + // + Copy( + inProfitPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWNS: + // + Copy( + inDrawdownPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OLDEST: + // + GetOldest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_YOUNGEST: + // + GetYoungest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAMES: + // + Copy( + samePositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_SAMES_OLDEST: + // + GetOldest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAMES_YOUNGEST: + // + GetYoungest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS: + // + Copy( + oppositPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_OLDEST: + // + GetOldest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_YOUNGEST: + // + GetYoungest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS: + // + Copy( + sameInProfitPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS: + // + Copy( + oppositInProfitPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWNS: + // + Copy( + sameInDrawdownPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWNS: + // + Copy( + oppositInDrawdownPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + } + + // + // Validate Result ... + result = HasChild(selecteds); + + // + // Cleanup Resources ... + + // + if (!result) + { + Clean(selecteds); + } + + // + Clean(samePositions); + Clean(oppositPositions); + Clean(inProfitPositions); + Clean(inDrawdownPositions); + Clean(sameInProfitPositions); + Clean(sameInDrawdownPositions); + Clean(oppositInProfitPositions); + Clean(oppositInDrawdownPositions); + + // + return result; +} + +// +struct XCATBEASymbolInfo +{ + // + // Properties ... + + // + string symbol; // Trading Symbol + + // + int longs; // All Long Trades + int shorts; // All Short Trades + + // + int trades; // All Trades + + // + int losses; // All Loosing Trades + int profits; // All Winning Trades + + // + datetime managedStart; // Managed Start Time + + // + int managedSLs; // Managed SL(s) + int managedTPs; // Managed TP(s) + int managedTrades; // Managed Trades + + // + double managedBalance; // Managed Start Balance + double managedProfits; // Managed Profit(s) + + // + // Constructor ... + XCATBEASymbolInfo() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + + // + longs = 0; + shorts = 0; + + // + trades = 0; + + // + losses = 0; + profits = 0; + + // + managedStart = NULL; + + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + + // + managedBalance = 0; + managedProfits = 0; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol); + + // + return result; + } + + // + bool IsSameAs(XCATBEASymbolInfo &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + // + string GetRestrictionDescription( + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD period // + ) + { + // + string result = NULL; + + // + if (!IsValid() && + period != XCATBEA_TRADE_RESTRICATION_NONE) + { + return result; + } + + // + result += + "-------------------" + "\n" + + "Restrictions: " + "\n" + + "-------------------" + "\n" + + "Symbol: " + ToXString(symbol) + "\n" + + "Period: " + ToXString(period) + "\n" + + "Start: " + ToFormatString(managedStart) + "\n" + + "Balance: " + ToXString(managedBalance) + "\n" + + "-------------------" + "\n" + + "Trades: " + ToXString(managedTrades) + "\n" + + "SL: " + ToXString(managedSLs) + "\n" + + "TP: " + ToXString(managedTPs) + "\n" + + "Profit: " + ToXString(managedProfits) + "\n" + + ""; + + // + return result; + } +}; + +// +struct XCATBEATradeSession +{ + // + // Properties ... + string start; // Session Start Time (hh:mm) + string end; // Session End Time (hh:mm) + string name; // Session Name + + // + // Constructor ... + XCATBEATradeSession() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + end = NULL; + name = NULL; + start = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(start) && + IsSpecifiedValid(end); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Check Session is Active or Not ... + bool IsActive(datetime time = NULL) + { + // + bool result = false; + + // + time = NormalizeTime(time); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsTimeInRange( + time, + start, + end // + ); + + // + return result; + } +}; + +struct XCATBEASymbolSession +{ + // + // Propeties ... + + // + string symbol; // Trading Symbol + XCATBEATradeSession sessions[]; // Trading Sessions + + // + // Constructor ... + XCATBEASymbolSession() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + SpecifiedClean(sessions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol); + + // + return result; + } + + // + // Check Allow Trade in Active Sessions ... + bool CanTrade(datetime time = NULL) + { + // + bool result = false; + + // + // Normalize Args ... + time = NormalizeTime(time); + + // + // Validating ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // if there is not any defined sessions for Symbol ... + // it's allow Trading in all times ... + result = !HasChild(sessions); + if (result) + { + return result; + } + + // + // Detect an Active Session ... + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].IsActive(time); + if (result) + { + break; + } + } + + // + return result; + } + + // +}; + +// +struct XCATBEATrade +{ + // + // Props ... + double swap; + double profit; + XSignal signal; + ulong positionID; + double commission; + XCATBEAStrategyConditions conditions; + ENUM_XCATBEA_TRADE_FINALIZATION finalize; + + // + datetime signaledAt; + datetime executedAt; + datetime finalizedAt; + + // + // Constructor ... + XCATBEATrade() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swap = 0; + profit = 0; + signal.Clean(); + commission = 0; + positionID = 0; + conditions.Clean(); + finalize = XCATBEA_TRADE_FINAL_NONE; + + // + signaledAt = NULL; + executedAt = NULL; + finalizedAt = NULL; + + // + ZeroMemory(this); + } + + /** + * Check Has Signal ... + * + * @return ( bool ) + */ + bool HasSignal() + { + // + bool result = false; + + // + result = signal.IsValid(); + + // + return result; + } + + /** + * Check Signal Executed or Not ... + * + * @return ( bool ) + */ + bool IsExecuted() + { + // + bool result = false; + + // + result = positionID > 0; + + // + return result; + } + + /** + * Check a Trade is Finalized or not ... + * + * @return ( bool ) + */ + bool IsFinalized() + { + // + bool result = false; + + // + result = HasSignal() && + IsExecuted() && + finalize != XCATBEA_TRADE_FINAL_NONE; + + // + return result; + } + + /** + * Generate Summary Info ... + * + * @return ( string ) + */ + string Summary() + { + // + string result = NULL; + + // + result = + // + ToXString("Swap", swap) + + ToXString("Profit", profit) + + ToXString("Commission", commission) + + ToXString("Finalize", ToXString(finalize)) + + ToXString("PositionID", positionID) + + ToXString("----------------") + "\n" + + ToXString("Signaled At", ToFormatString(signaledAt)) + + ToXString("Executed At", ToFormatString(executedAt)) + + ToXString("Finalized At", ToFormatString(finalizedAt)) + // + ; + + // + return result; + } + + /** + * Get Data Collection File Name ... + * + * @return ( string ) + */ + string GetFileName() + { + // + string result = NULL; + + // + bool hasSignal = HasSignal(); + bool isExecuted = IsExecuted(); + bool isFinalized = IsFinalized(); + if (!hasSignal && !isExecuted && !isFinalized) + { + return result; + } + + // + result = + // + signal.symbol + "\\" + + ToString(signal.type) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(positionID) + "_" + + ToString(signal.period) + "_" + + ToFormatString(signaledAt) + // + ; + + // + return result; + } + + /** + * Converts Model to String Representation ... + * + * @param onlySignals: Boolean, Specified Represent Only Signal or not ... + * + * @return ( string ) + */ + string ToString( + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + string result = NULL; + + // + // Generating Model Summary ... + string summary = Summary(); + + // + // Generating Signal Summary ... + string signalSummary = signal.ToString(); + + // + // Generating Conditions Summary ... + string conditionsSummary = conditions + .conditions + .GenerateSummary( + false, + true, + true, + false // Ignore False Conditions ... + ); + + // + if (includeSummary) + { + // + result += + ToXString("----------------") + "\n" + + ToXString("Summary: ") + "\n" + + ToXString("----------------") + "\n" + + summary + "\n"; + } + + // + if (includeSignal) + { + // + result += + ToXString("----------------") + "\n" + + ToXString("Signal: ") + "\n" + + ToXString("----------------") + "\n" + + signalSummary + "\n"; + } + + // + if (includeConditions) + { + // + result += + ToXString("----------------") + "\n" + + ToXString("Conditions: ") + "\n" + + ToXString("----------------") + "\n" + + conditionsSummary + "\n"; + } + + // + return result; + } + + string GetConditionsString() + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + conditions + .conditions + .GenerateScore( + bullishScore, + bearishScore // + ); + + // + string conditionsStr = + conditions + .conditions + .GenerateSummary( + false, + true, // Only Conditions ... + false, + false // Ignore False Conditions ... + ); + string condParts[]; + int condPartsCount = SplitContent( + condParts, + conditionsStr, + "\n" // + ); + if (IsValidSize(condPartsCount)) + { + // + conditionsStr = NULL; + while (HasChild(condParts)) + { + // + string iStr = condParts[0]; + ArrayRemove( + condParts, + 0, + 1 // + ); + + // + bool isLast = !HasChild(condParts); + + // + bool isCond = Contains( + "is", + iStr, + false // + ); + if (isCond) + { + // + string iParts[]; + int iPartsCount = SplitContent( + iParts, + iStr, + ":" // + ); + if (iPartsCount == 2) + { + // + string iVal = iParts[1]; + StringTrimLeft(iVal); + StringTrimRight(iVal); + bool isPassed = ToBoolean(iVal); + conditionsStr += (isPassed ? "" : "!") + "conditions." + iParts[0] + (!isLast ? " &&" : "") + "\n"; + } + } + } + SpecifiedClean(condParts); + } + else + { + conditionsStr = NULL; + } + + // + result = + "(" + "\n" + + "\\" + "\\" + " " + ToXString("Type", ToXString(signal.type)) + + "\\" + "\\" + " " + ToXString("Profit", profit) + + "\\" + "\\" + " " + ToXString("Finalize", ToXString(finalize)) + + "\\" + "\\" + " " + ToXString("PositionID", positionID) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + "\\" + "\\" + " " + ToXString("Signaled At", ToFormatString(signaledAt)) + + "\\" + "\\" + " " + ToXString("Executed At", ToFormatString(executedAt)) + + "\\" + "\\" + " " + ToXString("Finalized At", ToFormatString(finalizedAt)) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + "\\" + "\\" + " " + ToXString("Scores:") + "\n" + + "\\" + "\\" + " " + ToXString("Bullish", bullishScore) + + "\\" + "\\" + " " + ToXString("Bearish", bearishScore) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + conditionsStr + + (IsValid(conditionsStr) ? "" : "") + + ") && "; + + // + return result; + } +}; + +// +// Implementations ... +class XCXCATBEATradeManager : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAlert *alert; + XCTrade *trader; + bool drawSignal; + XCPOIDrawer *drawer; + XTimeTracker timeTracker; + XCDataCollector *collector; + + // + // Constructors ... + XCXCATBEATradeManager( + XCAlert *_alert, + XCTrade *_trader // + ) + { + // + alert = _alert; + trader = _trader; + drawSignal = true; + drawer = new XCPOIDrawer(); + + // + allowTrade = true; + allowLongs = true; + allowShorts = true; + + // + forceCloseAt = NULL; + isForceCloseAtTime = false; + + // + maxAllowedTPs = 0; + maxAllowedSLs = 0; + maxAllowedTrades = 0; + restrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; + + // + reportTrades = true; + reportSignals = true; + reportProtector = true; + reportAfterTradesBalance = true; + + // + SaveTrades(false); + + // + collector = new XCDataCollector(); + + // + // Setting Collector Path ... + string mPath = (IsValid(alert.GetPrefix()) + ? alert.GetPrefix() + "\\" + : "") + + trader.mAccount.GetCompany(); + collector.Path(mPath); + } + + // + // De Constructors ... + ~XCXCATBEATradeManager() + { + // + Clean(trades); + + // + timeTracker.Clean(); + + // + ZeroMemory(alert); + ZeroMemory(trader); + + // + delete drawer; + ZeroMemory(drawer); + + // + delete collector; + ZeroMemory(collector); + } + + // + // Properties ... + + // + bool SaveTrades() + { + return mSaveTrades; + } + + // + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + // + bool SaveSignals() + { + return mSaveSignals; + } + + // + void SaveSignals(bool value) + { + mSaveSignals = value; + } + + // + bool SaveWins() + { + return mSaveWins; + } + + // + void SaveWins(bool value) + { + mSaveWins = value; + } + + // + bool SaveLosts() + { + return mSaveLosts; + } + + // + void SaveLosts(bool value) + { + mSaveLosts = value; + } + + // + bool SaveRestrictions() + { + return mSaveRestrictions; + } + + // + void SaveRestrictions(bool value) + { + mSaveRestrictions = value; + } + + // + void SetForceCloseTradesAt( + string _forceCloseAt // + ) + { + forceCloseAt = _forceCloseAt; + } + + // + void SetTradeSession( + string symbol, + string start, + string end, + string name = NULL // + ) + { + // + // Validate Args ... + bool has = IsValid(end) && + IsValid(start) && + IsValid(symbol); + if (!has) + { + return; + } + + // + // Create Session ... + + // + XCATBEATradeSession session; + + // + session.end = end; + session.name = name; + session.start = start; + + // + int sessionIDX = -1; + has = FindSymbolSession( + sessionIDX, + symbol // + ); + + // + if (!has) + { + // + // Add New Symbol Session ... + + // + XCATBEASymbolSession iSymbolSession; + iSymbolSession.symbol = symbol; + + // + AddTradingSession( + session, + iSymbolSession // + ); + + // + AddRef( + iSymbolSession, + sessions // + ); + + // + iSymbolSession.Clean(); + } + else + { + // + // Update Trading Sessions of Exists Symbol Session ... + AddTradingSession( + session, + sessions[sessionIDX] // + ); + } + + // + // Cleanup Resources ... + session.Clean(); + } + + // + void SetTradeReports( + bool _reportTrades, + bool _reportSignals, + bool _reportProtector, + bool _reportRestrictions, + bool _reportAfterTradesBalance // + ) + { + // + reportTrades = _reportTrades; + reportSignals = _reportSignals; + reportProtector = _reportProtector; + reportRestrictions = _reportRestrictions; + reportAfterTradesBalance = _reportAfterTradesBalance; + } + + // + void SetTradePermissions( + bool _allowTrade, + bool _allowLongs, + bool _allowShorts // + ) + { + // + allowTrade = _allowTrade; + allowLongs = _allowLongs; + allowShorts = _allowShorts; + } + + // + void SetTradeRestrictions( + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD _period, + int _maxAllowedTPs, + int _maxAllowedSLs, + int _maxAllowedTrades // + ) + { + // + // Normalizing Args ... + _maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0); + _maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0); + _maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0); + + // + restrictionsPeriod = _period; + maxAllowedTPs = _maxAllowedTPs; + maxAllowedSLs = _maxAllowedSLs; + maxAllowedTrades = _maxAllowedTrades; + } + + // + // Tools ... + + /** + * Do All Position Managing Senaros ... + */ + void Manage() + { + // + // Handle Restrictions ... + HandleRestrictions(); + + // + // Check Contains Trades for Managing ... + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + // Update Required Infos of Trades ... + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + // Update Trade Data ... + trades[i].swap = iPosition.swap; + trades[i].profit = iPosition.profit; + } + + // + // Do Trade Protection ... + Protect(); + } + + /** + * Do All Position Protection Here ... + */ + void Protect() + { + // + string prefix = "Protector: "; + int targetDistance = 5; + + // + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + XPosition ownPosition[]; + XPosition ownLongPosition[]; + XPosition ownShortPosition[]; + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = + trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + AddRef( + iPosition, + ownPosition // + ); + + // + if (IsLong(iPosition.type)) + { + // + AddRef( + iPosition, + ownLongPosition // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPosition // + ); + } + } + + // + has = HasChild(ownPosition); + if (!has) + { + // + Clean(ownPosition); + Clean(ownLongPosition); + Clean(ownShortPosition); + + // + return; + } + + // + double swapSum = 0; + double profitSum = 0; + double commissionSum = 0; + + // + // Calculate Required Data On Collection ... + count = ArraySize(ownPosition); + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPosition[i]; + + // + swapSum += iPosition.swap; + profitSum += iPosition.profit; + commissionSum += iPosition.commission; + } + + // + // Do Collection Protectiong ... + + // + // Check Force Close ... + if (IsValid(forceCloseAt)) + { + // + datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseAt); + bool canForceClose = IsTimeInRange( + TimeCurrent(), + forceCloseTime // + ) && + !isForceCloseAtTime; + if (canForceClose) + { + // + isForceCloseAtTime = HandleForceCloseTrades(ownPosition); + + // + // Prevent Moving Forward ... + return; + } + } + + // + // Do Signle Protections ... + for (int i = 0; i < count; i++) + { + // + // Select Position ... + XPosition iPosition = ownPosition[i]; + int idx = -1; + has = HasTrade( + idx, + iPosition.ticket // + ); + if (!has) + { + continue; + } + + // + bool isLong = IsLong(iPosition.type); + double points = GetPoints(iPosition.symbol); + + // + // Handle RF On Targets ... + if (iPosition.profit > 0) + { + // + // Handle Risk Free On Targets ... + XTarget targets[]; + Copy( + trades[idx].signal.targets, + targets // + ); + int targetsCount = ArraySize(targets); + has = IsValidSize(targetsCount); + if (has) + { + // + for (int j = 0; j < targetsCount; j++) + { + // + XTarget jTarget = targets[j]; + + // + int appliedTargetIDX = -1; + + // + // Check Target is Applied Before or Not ... + has = + !trades[idx].signal.isTargetApplied + ? true + : trades[idx].signal.appliedTargetIDX < j; + if (!has) + { + continue; + } + + // + // Check Traget Validation ... + has = + iPosition.sl == 0 + ? true + : isLong + ? iPosition.sl < jTarget.target + : iPosition.sl > jTarget.target; + if (!has) + { + continue; + } + + // + double targetDelta = isLong + ? jTarget.target + (targetDistance * points) + : jTarget.target - (targetDistance * points); + + // + // Can Risk Free ... + bool canRF = + jTarget.doRF && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + + // + // Can Partial Close ... + bool canPC = + jTarget.volumeMultiplier > 0 && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + bool canRFPC = canRF || + canPC; + if (canRFPC) + { + // + // Handle Risk Free ... + bool isRFDone = false; + if (canRF) + { + // + double tp = iPosition.tp; + double sl = jTarget.target; + string comment = "RF On Target ..."; + isRFDone = trader.Modify( + iPosition.ticket, + sl, + tp, + comment // + ); + } + + // + // Handle Partail Close ... + bool isPCDone = false; + if (canPC) + { + // + double volume = jTarget.volumeMultiplier * iPosition.volume; + volume = NormalizeVolume(volume, iPosition.symbol); + string comment = "RF On Target ..."; + isPCDone = trader.ClosePartial( + iPosition.ticket, + volume, + comment // + ); + } + + // + // Handle Report Action ... + bool isRFPCDone = isRFDone || + isPCDone; + if (isRFPCDone) + { + // + trades[idx].signal.appliedTargetIDX = j; + trades[idx].signal.isTargetApplied = true; + + // + string message = prefix + + ToXString(iPosition.type) + + " Position: " + + ToXString(iPosition.ticket) + + (isRFDone ? " RF" : "") + + (isPCDone ? " PC" : "") + + " On Traget: " + ToXString(jTarget.target) + + " Successfully ..."; + HandleReportProtector(message); + } + } + } + } + } + } + } + + /** + * Check Specified Symbol is Active for + * Analysing or Open Trades ... + */ + bool IsActiveSession(string symbol) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + result = sessions[symbolSessionIDX].CanTrade(); + } + + // + return result; + } + + /** + * Check Signal Execution Conditions ... + * + * @param signal: XSignal instance reference ... + * @param executionResult: ENUM_X_SIGNAL_EXECUTION_RESULT member reference ... + * + * @return ( bool ) + */ + bool CheckSignal( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &executionResult // + ) + { + // + bool result = false; + + // + // Cleanup ... + executionResult = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Reporting Signal ... + if (reportSignals) + { + // + string message = signal.GetMessage("Provided"); + alert.SendAlert(message); + } + + // + SaveSignal(signal); + + // + // Check Trade Permission ... + if (!allowTrade) + { + // + result = false; + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + bool isLong = IsLong(signal.type); + bool isShort = IsShort(signal.type); + + // + bool isLongAndAllowed = + isLong && + allowLongs; + + // + bool isShortAndAllowed = + isShort && + allowShorts; + + // + result = isLongAndAllowed || + isShortAndAllowed; + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + // Check Symbol Info Exists or not ... + int symbolInfoIDX = -1; + bool isSymbolInfoExists = FindSymbolIndex( + symbolInfoIDX, + signal.symbol // + ); + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + signal.symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + // + result = sessions[symbolSessionIDX].CanTrade(); + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + + // + return result; + } + } + + // + // Check Trade Permissions Based on SL(s) Count ... + bool hasRestrictions = restrictionsPeriod != XCATBEA_TRADE_RESTRICATION_NONE; + if (hasRestrictions) + { + // + // Only Can Check Restrictions when + // Symbol Info Exists ... + if (isSymbolInfoExists) + { + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : symbols[symbolInfoIDX].managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : symbols[symbolInfoIDX].managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : symbols[symbolInfoIDX].managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + } + + // + // Report Error ... + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + + // + return result; + } + } + + // + return result; + } + + /** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCATBEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ + bool Execute( + XSignal &signal, + XCATBEAStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = HasTrade( + idx, + signal // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT executionResult; + + // + // Checking Signal For Execution ... + result = CheckSignal( + signal, + executionResult // + ); + if (result) + { + // + result = trader.ExecuteSignal( + signal, + executionResult // + ); + } + + // + // Alert Signal Execution ... + if (reportTrades) + { + // + string executionMessage = ToString(executionResult); + + // + string message = NULL; + if (result) + { + message = signal.GetMessage("Executed"); + } + else + { + message = signal.GetMessage("Failed due (" + executionMessage + ")"); + } + + // + alert.SendAlert(message); + } + + // + if (result) + { + // + // Draw Signal ... + if (drawSignal) + { + // + XCSignalObject *iObj; + isExists = drawer.DrawSignal( + signal, + iObj // + ); + + // + if (isExists) + { + // + mObjects.Add(iObj); + ZeroMemory(iObj); + } + } + + // + // Create Symbol Info Struct ... + XCATBEASymbolInfo iSymbolInfo; + + // + iSymbolInfo.trades = 1; + iSymbolInfo.managedTrades = 1; + iSymbolInfo.symbol = signal.symbol; + + // + bool isLong = IsLong(signal.type); + if (isLong) + { + iSymbolInfo.longs = 1; + } + else + { + iSymbolInfo.shorts = 1; + } + + // + // Fill Balance for Restrications ... + bool hasRestrictions = HasRestrictions(); + if (hasRestrictions) + { + // + // Read Balance ... + double balance = trader.mAccount.GetBalance(); + iSymbolInfo.managedBalance = balance; + iSymbolInfo.managedStart = TimeCurrent(); + } + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + // Create Trade Struct ... + XCATBEATrade iTrade; + + // + ulong positionID = trader.GetLastOpenPositionTicket(); + double commission = trader.GetPositionCommission(positionID); + + // + iTrade.signal = signal; + iTrade.conditions = conditions; + iTrade.positionID = positionID; + iTrade.commission = commission; + iTrade.signaledAt = signal.time; + iTrade.executedAt = TimeCurrent(); + + // + AddRef( + iTrade, + trades // + ); + } + + // + return result; + } + + /** + * Retrieve Specified Positions ... + * + * @param positions: XPosition instance Reference Array, which holds Founded Positions ... + * @param symbol: string, Specified Symbol Name ... + * @param provider: string, Specified Provider Name ... + * @param period: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetPositions( + XPosition &positions[], + string symbol, + string provider, + ENUM_TIMEFRAMES period // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = + IsValid(symbol) && + IsValid(period) && + IsValid(provider); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + symbol, + provider, + period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + /** + * Handle Position Take Profit ... + * + * @param deal: XDeal instance reference ... + */ + void HandleTP(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XCATBEA_TRADE_FINAL_TP; + + // + // Save Trade ... + SaveWin(trades[idx]); + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "TP: " + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + XCATBEASymbolInfo iSymbolInfo; + + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Stop Loss ... + * + * @param deal: XDeal instance reference ... + */ + void HandleSL(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XCATBEA_TRADE_FINAL_SL; + + // + // Save Trade ... + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "SL: " + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + bool isInProfit = trades[idx].profit > 0; + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + XCATBEASymbolInfo iSymbolInfo; + + // + if (isInProfit) + { + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + } + else + { + // + iSymbolInfo.losses = 1; + iSymbolInfo.managedSLs = 1; + } + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Force Close ... + * + * @param deal: XDeal instance reference ... + */ + void HandleForceClose(const XPosition &position) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + position.ticket // + ); + if (!isExists) + { + return; + } + + // + bool isInProfit = position.profit > 0; + + // + // Apply Required Data ... + trades[idx].swap = position.swap; + trades[idx].profit = position.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].commission = position.commission; + trades[idx].finalize = isInProfit + ? XCATBEA_TRADE_FINAL_CLOSE_IN_PROFIT + : XCATBEA_TRADE_FINAL_CLOSE_IN_LOSE; + + // + // Save Trade ... + SaveTrade(trades[idx]); + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + // Handle Balance Reporting ... + string prefix = "Force Close " + + (isInProfit + ? "Profit" + : "Loss") + + ": " + + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + XCATBEASymbolInfo iSymbolInfo; + + // + if (isInProfit) + { + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + } + else + { + // + iSymbolInfo.losses = 1; + iSymbolInfo.managedSLs = 1; + } + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ULONG ... + * @param profit: double ... + * @param comment: string ... + */ + void HandlePartiallyClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + // Handle Balance Reporting ... + string prefix = "Partially Closed: " + ToXString(ticket); + + // + // Handle Balance Reporting ... + HandleReportBalance(prefix); + } + + /** + * Handle Force Close Trades ... + */ + bool HandleForceCloseTrades( + XPosition &positions[] // + ) + { + // + bool result = false; + + // + result = HasChild(positions); + if (!result) + { + return result; + } + + // + string prefix = "Protector: "; + string comment = "Force Close ..."; + + // + int closedsCount = trader.Close( + positions, + comment // + ); + result = IsValidSize(closedsCount); + if (result) + { + // + string message = prefix + "Force Close (" + ToXString(closedsCount) + ") Trades at Specified Time ..."; + HandleReportProtector(message); + } + + // + return result; + } + + // + // TODO: Complete this ... + void HandleGuard() + { + } + + /** + * Find Executed Trade by Providing Position Ticket ... + * + * @param index: int reference, holding founded item index ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + ticket > 0 && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XCATBEATrade iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.IsExecuted() && + iTrade.positionID == ticket; + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Trade Item By Signal ... + * + * @param index: int reference, holding founded item index ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + signal.IsValid() && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XCATBEATrade iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.signal.IsSameAs(signal); + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove a Trade From List ... + * + * @param index: int ... + */ + void RemoveTrade(int index) + { + // + bool has = + HasChild(trades) && + IsValidIndex(index) && + index < ArraySize(trades); + if (!has) + { + return; + } + + // + ArrayRemove( + trades, + index, + 1 // + ); + } + + // + // Protected ... + protected: + // + // Tools ... + + // + string GetTradeFilePath(XCATBEATrade &trade) + { + // + string fileName = trade.GetFileName(); + + // + return GetTradeFilePath(fileName); + } + + // + string GetTradeFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Trades" + "\\" + fileName); + + // + return result; + } + + // + string GetSignalFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Signals" + "\\" + fileName); + + // + return result; + } + + // + string GetWinsFilePath(XCATBEATrade &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToXString(trade.signal.period) + "_wins"); + + // + return result; + } + + // + string GetLostsFilePath(XCATBEATrade &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToXString(trade.signal.period) + "_losts"); + + // + return result; + } + + // + string GetRestrictionsFilePath(string symbol) + { + // + string result = NULL; + + // + if (!IsValid(symbol)) + { + return result; + } + + // + result = collector + .GetFilePath("Restrictions" + "\\" + symbol); + + // + return result; + } + + // + void HandleReportBalance(string prefix = NULL) + { + // + if (!reportAfterTradesBalance) + { + return; + } + + // + double balance = trader.mAccount.GetBalance(); + string currency = trader.mAccount.GetCurrency(); + + // + string message = + (IsValid(prefix) + ? prefix + " | " + : "") + + "Account Balance: " + ToXString(balance) + currency; + alert.SendAlert(message); + } + + // + void HandleReportProtector(string message = NULL) + { + // + if (!reportProtector) + { + return; + } + + // + alert.SendAlert(message); + } + + // + // Save Trades ... + bool SaveTrade( + XCATBEATrade &trade, + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + bool result = false; + + // + if (!mSaveTrades) + { + return result; + } + + // + string filePath = GetTradeFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = trade.ToString( + includeSummary, + includeSignal, + includeConditions // + ); + + // + result = collector.Save( + filePath, + content // + ); + + // + return result; + } + + // + // Save Signals ... + bool SaveSignal(XSignal &signal) + { + // + bool result = false; + + // + // Check Signal Save is Enabled ... + if (!mSaveSignals) + { + return result; + } + + // + // Check Signal Validation ... + if (!signal.IsValid()) + { + return result; + } + + // + // Retrieve Signal File Name ... + string signalFileName = signal.GetFileName(); + result = IsValid(signalFileName); + if (!result) + { + return result; + } + + // + // Retriev and Validate File Name ... + string filePath = GetSignalFilePath(signalFileName); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Generate Content ... + string content = ""; + content += + ToXString("----------------") + "\n" + + ToXString("Signal: ") + "\n" + + ToXString("----------------") + "\n" + + signal.ToString() + "\n"; + content += + ToXString("----------------") + "\n" + + ToXString("Conditions: ") + "\n" + + ToXString("----------------") + "\n" + + signal.conditions + "\n"; + + // + // Save Content to File ... + result = collector.Save( + filePath, + content // + ); + + // + // Return Result ... + return result; + } + + // + bool SaveWin(XCATBEATrade &trade) + { + // + bool result = false; + + // + if (!mSaveWins) + { + return result; + } + + // + string filePath = GetWinsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveLost(XCATBEATrade &trade) + { + // + bool result = false; + + // + if (!mSaveLosts) + { + return result; + } + + // + string filePath = GetLostsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveRestrictions(XCATBEASymbolInfo &info) + { + // + bool result = false; + + // + if (!mSaveRestrictions) + { + return result; + } + + // + result = info.IsValid(); + if (!result) + { + return result; + } + + // + string filePath = GetRestrictionsFilePath(info.symbol); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = info.GetRestrictionDescription(restrictionsPeriod); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + // Symbol Info ... + + // + bool FindSymbolIndex( + int &index, + XCATBEASymbolInfo &item // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = HasChild(symbols); + if (!result) + { + return result; + } + + // + index = FindIndex( + item, + symbols // + ); + + // + result = IsValidIndex(index); + + // + return result; + } + + // + bool FindSymbolIndex( + int &index, + string symbol // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(symbols); + if (!result) + { + return result; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + result = symbols[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + void AddOrUpdateSymbolInfo(XCATBEASymbolInfo &item) + { + // + bool has = item.IsValid(); + if (!has) + { + return; + } + + // + int index = -1; + bool isExists = FindSymbolIndex( + index, + item // + ); + if (!isExists) + { + // + AddRef( + item, + symbols // + ); + } + else + { + // + symbols[index].longs += item.longs; + symbols[index].shorts += item.shorts; + symbols[index].trades += item.trades; + symbols[index].losses += item.losses; + symbols[index].profits += item.profits; + symbols[index].managedSLs += item.managedSLs; + symbols[index].managedTPs += item.managedTPs; + symbols[index].managedTrades += item.managedTrades; + symbols[index].managedProfits += item.managedProfits; + + // + // Handle Remove on Managed SL based On Managed TP ... + if (item.managedTPs > 0) + { + // + symbols[index].managedSLs -= item.managedTPs; + if (symbols[index].managedSLs < 0) + { + symbols[index].managedSLs = 0; + } + } + + // + // Handle Remove on Managed TP based On Managed SL ... + if (item.managedSLs > 0) + { + // + symbols[index].managedTPs -= item.managedSLs; + if (symbols[index].managedTPs < 0) + { + symbols[index].managedTPs = 0; + } + } + } + } + + // + void ResetSymbolsRestrictions() + { + // + bool has = HasChild(symbols); + if (has) + { + // + string prefix = "Protector: "; + + // + datetime start = TimeCurrent(); + double balance = trader.mAccount.GetBalance(); + bool hasRestrictions = HasRestrictions(); + if (!hasRestrictions) + { + // + balance = 0; + start = NULL; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + XCATBEASymbolInfo iInfo = symbols[i]; + if (reportRestrictions) + { + // + string message = iInfo.GetRestrictionDescription(restrictionsPeriod); + alert.SendAlert(message); + } + SaveRestrictions(iInfo); + + // + symbols[i].managedSLs = 0; + symbols[i].managedTPs = 0; + symbols[i].managedTrades = 0; + symbols[i].managedProfits = 0; + symbols[i].managedStart = start; + symbols[i].managedBalance = balance; + + // + iInfo.Clean(); + } + + // + string message = prefix + "Reset Symbols Restrictions"; + HandleReportProtector(message); + } + } + + // + void HandleRestrictions() + { + // + bool isNewDay = timeTracker.IsNewDay(); + bool isNewHour = timeTracker.IsNewHour(); + bool isNewWeek = timeTracker.IsNewWeek(); + bool isNewMonth = timeTracker.IsNewMonth(); + + // + // Reset Force Closed Flag on new Day Starts ... + if (isNewDay) + { + isForceCloseAtTime = false; + } + + // + bool canResetRestrictions = + ( + // + // Hourly ... + (isNewHour && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_HOURLY) + // + || + // + // Daily ... + (isNewDay && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_DAILY) + // + || + // + // Weekly ... + (isNewWeek && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_WEEKLY) + // + || + // + // Monthly ... + (isNewMonth && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_MONTHLY) + // + ) + // + ; + if (canResetRestrictions) + { + ResetSymbolsRestrictions(); + } + } + + // + // Symbol Session ... + + // + bool FindSymbolSession( + int &index, + string symbol // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(sessions); + if (!result) + { + return result; + } + + // + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + void AddTradingSession( + XCATBEATradeSession &session, + XCATBEASymbolSession &symbolSession // + ) + { + // + bool has = session.IsValid() && + symbolSession.IsValid(); + if (!has) + { + return; + } + + // + // Check Session Exists in Symbol Session ... + bool isExists = false; + if (HasChild(symbolSession.sessions)) + { + // + int count = ArraySize(symbolSession.sessions); + for (int i = 0; i < count; i++) + { + // + isExists = symbolSession.sessions[i].end == session.end && + symbolSession.sessions[i].start == session.start; + if (isExists) + { + break; + } + } + } + + // + if (!isExists) + { + // + AddRef( + session, + symbolSession.sessions // + ); + } + } + + // + // Private ... + private: + // + // Props ... + + // + bool allowTrade; + bool allowLongs; + bool allowShorts; + + // + string forceCloseAt; + bool isForceCloseAtTime; + + // + int maxAllowedTPs; + int maxAllowedSLs; + int maxAllowedTrades; + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD restrictionsPeriod; + bool HasRestrictions() + { + return restrictionsPeriod != XCATBEA_TRADE_RESTRICATION_NONE; + } + + // + bool mSaveWins; + bool mSaveLosts; + bool mSaveTrades; + bool mSaveSignals; + bool mSaveRestrictions; + + // + bool reportTrades; + bool reportSignals; + bool reportProtector; + bool reportRestrictions; + bool reportAfterTradesBalance; + + // + CArrayObj mObjects; + + // + XCATBEATrade trades[]; + XCATBEASymbolInfo symbols[]; + XCATBEASymbolSession sessions[]; +}; + +// diff --git a/BKPS/14040626/XCATBEA/Libraries/xcatbea.lib.mq5 b/BKPS/14040626/XCATBEA/Libraries/xcatbea.lib.mq5 new file mode 100644 index 0000000..992ab89 --- /dev/null +++ b/BKPS/14040626/XCATBEA/Libraries/xcatbea.lib.mq5 @@ -0,0 +1,2996 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCATBEA Lib +// Description: Library for XCATBEA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Library for XCATBEA Signaller" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" + +// +// Definiions ... + +// +#define XLiquidityToken "XLQ"; +#define XTriggerBlockToken "XTRG"; + +// +struct XTriggerBlock +{ + // + // Props ... + XBoxZone ob; // Order Block + XBoxZone fvg; // Fair Value Gap + XOHCL swingBar; // Swing of Trigger + XBoxZone trigger; // Trigger Block + XBoxZone rLiquidity; // Reversal Liquidity + XBoxZone fLiquidity; // Following Liquidity + + // + XSignal signal; // Pepared Signal + + // + // Constructor ... + XTriggerBlock() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ob.Clean(); + fvg.Clean(); + signal.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = ob.IsValid() && + fvg.IsValid() && + trigger.IsValid(); + + // + return result; + } + + // + bool IsBullish() + { + return IsValid() && + ob.IsBullish(); + } + + // + bool IsBearish() + { + return IsValid() && + ob.IsBearish(); + } + + // + int ToIndex() + { + return trigger.ToIndex(); + } + + // + int FromIndex() + { + return trigger.FromIndex(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (IsValid()) + { + result = ob.dir; + } + + // + return result; + } + + // +}; + +// +// Trigger Block Validation Rules ... +struct XTriggerBlockValidationRules +{ + // + // Props ... + bool forceHasSwing; // Force Block to Has Propper Swing ... + bool forceOBBarType; // Force Order Block to Has InDirectional Bars ... + int minRequiredOBBar; // Min Required OB Bar ... + bool forceFVGBarType; // Force Fair Value Gaps Bars Type ... + int liquidityLoopback; // Liquidity Detection Loopback ... + double maxAllowedRange; // Max Allowed Order Block Range ... + double minAllowedRange; // Min Allowed Order Block Range ... + bool forceHasFLiquidity; // Force Order Block To Has Reversal Liquidity ... + bool forceHasRLiquidity; // Force Order Block to Has Following Liquidity ... + bool validateGapSequence; // Validate Fair Value Gaps Bar Sequences ... + int minAllowedBlockLength; // Min Allowed Block Length ... + bool validateBlockEdgeBreakout; // Validate Order Block Edge Breakeout ... + + // + // Constructor(s) ... + XTriggerBlockValidationRules() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + maxAllowedRange = 0; + minAllowedRange = 0; + minRequiredOBBar = 0; + liquidityLoopback = 0; + forceHasSwing = false; + forceOBBarType = false; + forceFVGBarType = false; + minAllowedBlockLength = 0; + forceHasFLiquidity = false; + forceHasRLiquidity = false; + validateGapSequence = false; + validateBlockEdgeBreakout = false; + + // + ZeroMemory(this); + } +}; + +// +// Trigger Block Filters ... +struct XTriggerBlockFilters +{ + // + // Props ... + bool filterBasedOnKI; // Filter Based On KI Flats ... + bool filterBasedOnPV; // Filter Based On PV ... + bool filterBasedOnSar; // Filter Based On SAR ... + bool filterBasedOnRSI; // Filter Based On RSI ... + bool filterBasedOnADX; // Filter Based On ADX ... + bool filterBasedOnATR; // Filter Based On ATR ... + bool filterBasedOnTrend; // Filter Based On Trend ... + bool filterBasedOnDelta; // Filter Based On Delta ... + bool filterBasedOnVolume; // Filter Based On Volume ... + bool filterBasedOnSignalBar; // Filter Based on Signal Bar ... + bool filterBasedOnHKSignalBar; // Filter Based On HK Signal Bar ... + + // + int bosLoopback; // PV Based Filtering BOS Lookup ... + + // + bool forceSarSwitched; // SAR Switched on Sides for Filtering ... + bool forceSarOnBothSide; // SAR Check on Both Sides for Filtering ... + bool forceSarHasBreakout; // SAR Must SAR Must Breakout ... + bool forceSarHasReversalSide; // SAR Must SAR Must Has Reversal Direction ... + + // + bool forceHasRSITrending; // RSI Must Has Trending ... + bool forceHasRSIVPattern; // RSI Must Has Pattern ... + bool forceHasRSICrossing; // RSI Must Has Crossing Levels ... + + // + bool forceHasADXTrending; // ADX Must Has Trending ... + bool forceHasADXCrossing; // ADX Must Has Crossing +DI/-DI ... + + // + bool forceHasATRTrending; // ATR Must Has Trending ... + bool forceHasATRBreakout; // ATR Must Has Breakout ... + + // + bool forceHasTrendDir; // TREND Must Has Following Direction ... + bool forceHasTrendPlace; // TREND Place Based Filtering ... + bool forceHasTrendChange; // TREND Change Filtering ... + bool forceHasTrendTrending; // TREND Must Has Trending ... + bool forceHasTrendRejection; // TREND Line Must Rejected ... + bool forceHasTrendLineInside; // TREND Line has Inside ... + bool forceHasTrendDirOnBothSide; // TREND Must Has Following Direction in Both Side ... + + // + // Constructor(s) ... + XTriggerBlockFilters() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + filterBasedOnKI = false; + filterBasedOnPV = false; + filterBasedOnSar = false; + filterBasedOnRSI = false; + filterBasedOnADX = false; + filterBasedOnATR = false; + filterBasedOnTrend = false; + filterBasedOnDelta = false; + filterBasedOnVolume = false; + filterBasedOnSignalBar = false; + filterBasedOnHKSignalBar = false; + + // + bosLoopback = 0; + + // + forceSarSwitched = false; + forceSarOnBothSide = false; + forceSarHasBreakout = false; + forceSarHasReversalSide = false; + + // + forceHasRSITrending = false; + forceHasRSIVPattern = false; + forceHasRSICrossing = false; + + // + forceHasADXTrending = false; + forceHasADXCrossing = false; + + // + forceHasATRTrending = false; + forceHasATRBreakout = false; + + // + forceHasTrendDir = false; + forceHasTrendPlace = false; + forceHasTrendChange = false; + forceHasTrendTrending = false; + forceHasTrendRejection = false; + forceHasTrendLineInside = false; + forceHasTrendDirOnBothSide = false; + + // + ZeroMemory(this); + } +}; + +// +// Extensions ... + +/** + * Get Newest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetYoungest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + datetime selected = NULL; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + !IsValid(selected) + ? true + : tbs[i].trigger.from > selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.from; + } + } + + // + return result; +} + +/** + * Get Oldest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetOldest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + datetime selected = NULL; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + !IsValid(selected) + ? true + : tbs[i].trigger.from < selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.from; + } + } + + // + return result; +} + +/** + * Get Highest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetHighest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + double selected = 0; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + selected <= 0 + ? true + : tbs[i].trigger.lower > selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.lower; + } + } + + // + return result; +} + +/** + * Get Lowest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetLowest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + double selected = 0; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + selected <= 0 + ? true + : tbs[i].trigger.upper < selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.upper; + } + } + + // + return result; +} + +/** + * Find Trigger Block Index inside a Colletion ... + */ +bool FindTriggerBlockIndex( + int &index, + XTriggerBlock &tb, + XTriggerBlock &tbs[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = tb.IsValid(); + if (!result) + { + return result; + } + + // + bool isExists = false; + bool has = HasChild(tbs); + if (has) + { + // + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + isExists = tb.trigger.IsSameAs(tbs[i].trigger); + if (isExists) + { + // + index = i; + break; + } + } + } + + // + result = + isExists && + IsValidIndex(index); + + // + return result; +} + +/** + * Remove Specified Trigger Block from a Collection, if Exists ... + * + * @param tb: XTriggerBlock instance reference, Specified Trigger Block for Checking ... + * @param tbs: XTriggerBlock instance reference Array, Collection of Trigger Blocks ... + * + * @return ( bool ) + */ +bool RemoveTriggerBlock( + XTriggerBlock &tb, + XTriggerBlock &tbs[] // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = tb.IsValid() && + HasChild(tbs); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindTriggerBlockIndex( + idx, + tb, + tbs // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + tbs, + idx, + 1 // + ); + + // + return result; +} + +/** + * Detect a TriggerBlock which Specified TriggerBlock is Inside of it ... + * + * @param tb: XTriggerBlock instance reference, Specified Trigger Block for Checking ... + * @param insideTB: XTriggerBlock instance reference, Holds founded inside Trigger Block ... + * @param tbs: XTriggerBlock instance collection, Specified Collection for Checking ... + * @param minimumLengthBetweenTBs: int, Minimum Bars between two Trigger Blocks ... + * + * @return ( int ) founded Inside TriggerBlock index ... + */ +int DetectInsideTriggerBlock( + XTriggerBlock &tb, + XTriggerBlock &insideTB, + XTriggerBlock &tbs[], + int minimumLengthBetweenTBs = 5 // +) +{ + // + int result = -1; + + // + // Normalize Args ... + minimumLengthBetweenTBs = NormalizeInt(minimumLengthBetweenTBs, 3); + + // + // Check Collection has Childs ... + bool has = HasChild(tbs); + if (!has) + { + return result; + } + + // + insideTB.Clean(); + bool isBullish = tb.IsBullish(); + bool isBearish = tb.IsBearish(); + + // + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + // Check Trigger Block Conditions ... + bool isInside = + // + // Check Not Same ... + !tb.trigger.IsSameAs(tbs[i].trigger) && + // + // Check Direction ... + tb.trigger.dir == tbs[i].trigger.dir && + // + // Check Length of TBS ... + (minimumLengthBetweenTBs <= 0 + ? true + : tb.trigger.FromIndex() + minimumLengthBetweenTBs <= tbs[i].trigger.FromIndex()) && + // + // Check Inside it ... + (isBullish + ? (tb.trigger.lower < tbs[i].trigger.upper && + tb.trigger.lower > tbs[i].trigger.lower && + tb.trigger.lower < tbs[i].trigger.GetMid()) + : (tb.trigger.upper > tbs[i].trigger.lower && + tb.trigger.upper < tbs[i].trigger.upper && + tb.trigger.upper > tbs[i].trigger.GetMid())) && + // + // Check Last ... + (!insideTB.IsValid() + ? true + : isBullish + ? insideTB.trigger.upper > tbs[i].trigger.upper + : insideTB.trigger.lower < tbs[i].trigger.lower) + // + ; + if (isInside) + { + // + result = i; + insideTB = tbs[i]; + } + } + + // + return result; +} + +/** + * Detect Trigger Block ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param triggerBlock: XTriggerBlock Refrence, holds Detected Trigger Block ... + * @param conditions: X121XCatbConditions Refrence, holds Trigger Block Conditions ... + * @param validations: XTriggerBlockValidationRules Refrence, Provides Trigger Block Validation Rules ... + * @param filters: XTriggerBlockFilters Refrence, Provides Trigger Block Filters ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Conditions reading ... + * + * @return ( bool ) + */ +bool DetectTriggerBlock( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockValidationRules &validations, + XTriggerBlockFilters &filters, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + conditions.Clean(); + triggerBlock.Clean(); + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 0); + + // + // Validate Args ... + result = + helper != NULL && + barAnalyser != NULL; + if (!result) + { + return result; + } + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + bool has = false; + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + + // + // Initial Requirements ... + + // + // Required Bars ... + XOHCL zBar; + XOHCL cBar; + result = + result && + zBar.Init( + symbol, + period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + + // + // Here we Must Detect Order Block ... + // then Detect FVG ... + // then Prepare Trigger Box ... + + // + // Select Application Bar ... + XOHCL iBar; + if (barIndex == 0) + { + iBar = cBar; + } + else if (barIndex > 0) + { + iBar = zBar; + } + iBar = cBar; + result = + result && + iBar.IsValid(); + + // + // Detect Order Block ... + result = + result && + barAnalyser + .IsOB( + iBar, + triggerBlock.ob, + false, + false // + ); + + // + // Detect Fair Value Gap ... + result = + result && + barAnalyser + .IsFVG( + iBar, + triggerBlock.fvg, + false // + ); + + // + // Check Result and Create Trigger Box based on it ... + if (result) + { + // + triggerBlock.trigger = triggerBlock.ob; + triggerBlock.trigger.type = XTriggerBlockToken; + + // + // Update Upper and Lower ... + int toIDX = triggerBlock.ob.ToIndex(); + int fromIDX = triggerBlock.ob.FromIndex(); + + // + iBar.Clean(); + result = iBar.Init( + symbol, + period, + toIDX // + ); + if (result) + { + // + double iLL = iBar.FindLowest(fromIDX - toIDX, MODE_LOW); + double iHH = iBar.FindHighest(fromIDX - toIDX, MODE_HIGH); + + // + triggerBlock.trigger.upper = MathMax(iHH, triggerBlock.trigger.upper); + triggerBlock.trigger.lower = MathMin(iLL, triggerBlock.trigger.lower); + } + + // + iBar.Clean(); + } + + // + // Apply Validations ... + if (result) + { + // + result = ValidateTriggerBlock( + helper, + barAnalyser, + triggerBlock, + conditions, + validations, + barIndex, + loopback // + ); + + // + if (!result) + { + triggerBlock.Clean(); + } + } + + // + // Apply Filtering ... + if (result) + { + // + result = FilterTriggerBlock( + helper, + barAnalyser, + triggerBlock, + conditions, + filters, + barIndex, + loopback // + ); + + // + if (!result) + { + triggerBlock.Clean(); + } + } + + // + // Summarizing Result ... + result = + result && + triggerBlock.IsValid(); + + // + // Preparing Signal ... + if (result) + { + // + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + zBar.Clean(); + cBar.Clean(); + + // + if (!result) + { + triggerBlock.Clean(); + } + + // + return result; +} + +/** + * Validate a Trigger Block ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param triggerBlock: XTriggerBlock Refrence, Trigger Block ... + * @param conditions: X121XCatbConditions Refrence, Trigger Block Conditions ... + * @param validations: XTriggerBlockValidationRules Refrence, Provides Trigger Block Validation Rules ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Conditions reading ... + * + * @return ( bool ) + */ +bool ValidateTriggerBlock( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockValidationRules &validations, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Checking Conditions ... + + // + // Normalize Args ... + conditions.Clean(); + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 0); + + // + // Validate Args ... + result = + helper != NULL && + barAnalyser != NULL && + triggerBlock.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Market Conditions ... + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + XOHCL iBar; + int count = 0; + int toIDX = -1; + int fromIDX = -1; + bool has = false; + bool isBullish = triggerBlock.IsBullish(); + bool isBearish = triggerBlock.IsBearish(); + double points = GetPoints(triggerBlock.ob.symbol); + ENUM_X_DIRECTION iDir = triggerBlock.GetDirection(); + + // + // Checking Conditions ... + + // + // Range Validation ... + + // + // Max Allowed OB Range ... + if (result && + validations.maxAllowedRange > 0) + { + // + double iRange = triggerBlock.ob.GetRange(); + result = iRange <= (validations.maxAllowedRange * points); + } + + // + // Min Allowed OB Range ... + if (result && + validations.minAllowedRange > 0) + { + // + double iRange = triggerBlock.ob.GetRange(); + result = iRange >= (validations.maxAllowedRange * points); + } + + // + // Has Swing ... + if (result && + validations.forceHasSwing) + { + // + bool isSwing = false; + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + ENUM_X_DIRECTION swingDir = X_DIRECTION_NONE; + for (int i = toIDX; i <= fromIDX; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + isSwing = + has && + barAnalyser + .IsSimpleSwing( + iBar, + swingDir // + ); + if (isSwing && + swingDir == iDir) + { + break; + } + + // + iBar.Clean(); + } + + // + result = + isSwing && + iBar.IsValid() && + swingDir == iDir; + if (result) + { + // + // Initialize Swing Bar ... + result = triggerBlock + .swingBar + .Init( + iBar.symbol, + iBar.period, + iBar.Index() + 2 // + ); + } + + // + iBar.Clean(); + } + + // + // Force FVG Bar Types ... + if (result && + validations.forceFVGBarType) + { + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize iBar ... + result = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + result = + result && + iDir == iBar.GetDirection(); + + // + iBar.Clean(); + + // + if (!result) + { + break; + } + } + + // + iBar.Clean(); + } + + // + // Force OB Start By InDirectional Bars ... + if (result && + validations.forceOBBarType) + { + // + count = 0; + fromIDX = triggerBlock.fvg.FromIndex() + 1; + int sIDX = fromIDX; + has = true; + while (has) + { + // + // Initialize iBar .. + has = iBar.Init( + conditions.symbol, + conditions.period, + fromIDX // + ); + has = has && + iDir == Opposit(iBar.GetDirection()); + if (has) + { + count++; + } + + // + fromIDX++; + } + + // + int required = + validations.minRequiredOBBar > 0 + ? validations.minRequiredOBBar + : 1; + + // + result = count >= required; + + // + // Update Trigger Block Box based on OB Bar Types ... + if (result) + { + // + result = iBar.Init( + conditions.symbol, + conditions.period, + sIDX // + ); + if (result) + { + // + datetime iFrom = GetBarTime( + conditions.symbol, + conditions.period, + sIDX + count // + ); + double iLL = iBar.FindLowest(count, MODE_LOW); + double iHH = iBar.FindHighest(count, MODE_HIGH); + + // + triggerBlock.trigger.from = iFrom; + triggerBlock.trigger.upper = MathMax(iHH, triggerBlock.trigger.upper); + triggerBlock.trigger.lower = MathMin(iLL, triggerBlock.trigger.lower); + } + } + + // + iBar.Clean(); + } + + // + // Force Fair Value Gap to Following Sequence ... + if (result && + validations.validateGapSequence) + { + // + XOHCL iPBar; + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex() - 1; + for (int i = toIDX; i < fromIDX; i++) + { + // + result = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + result = + result && + iBar.GetPreviousBar(iPBar); + result = + result && + (isBullish + ? iBar.low > iPBar.low + : iBar.high < iPBar.high); + if (!result) + { + break; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + // Validate OB Edge Breakeout Using Gaps End Bar ... + if (result && + validations.validateBlockEdgeBreakout) + { + // + // Initialize Gap End Bar ... + toIDX = triggerBlock.fvg.ToIndex(); + result = iBar.Init( + conditions.symbol, + conditions.period, + toIDX // + ); + + // + result = + result && + (isBullish + ? iBar.open < triggerBlock.ob.upper && + iBar.close > triggerBlock.ob.upper + : iBar.open > triggerBlock.ob.lower && + iBar.close < triggerBlock.ob.lower); + + // + // Here we Can Apply Edge Breakout Using Fibo ... + + // + iBar.Clean(); + } + + // + // Force Block to Has Liquidity ... + if (result && + validations.liquidityLoopback > 0 && + (validations.forceHasFLiquidity || + validations.forceHasRLiquidity)) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + ENUM_X_DIRECTION iLiqDir = X_DIRECTION_NONE; + for (int i = toIDX; i < fromIDX + validations.liquidityLoopback; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + has = + has && + barAnalyser + .IsRejected( + iBar, + iLiqDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + + // + bool isFLiq = + has && + iLiqDir == iDir; + if (isFLiq && + validations.forceHasFLiquidity && + !triggerBlock.fLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iLiqDir, + triggerBlock.fLiquidity, + triggerBlock.trigger.to // + ); + } + + // + bool isRLiq = + has && + iLiqDir == Opposit(iDir); + if (isRLiq && + validations.forceHasRLiquidity && + !triggerBlock.rLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iLiqDir, + triggerBlock.rLiquidity, + triggerBlock.trigger.to // + ); + } + + // + // Here We Can Apply Liquidity Validations ... + ValidateTriggerBlockLiquidities( + helper, + barAnalyser, + triggerBlock, + conditions, + validations // + ); + + // + // Check Liquidities ... + has = (!validations.forceHasFLiquidity + ? true + : triggerBlock.fLiquidity.IsValid()) && + (!validations.forceHasRLiquidity + ? true + : triggerBlock.rLiquidity.IsValid()); + + // + iBar.Clean(); + + // + if (has) + { + break; + } + } + + // + // Check Result ... + result = (!validations.forceHasFLiquidity + ? true + : triggerBlock.fLiquidity.IsValid()) && + (!validations.forceHasRLiquidity + ? true + : triggerBlock.rLiquidity.IsValid()); + + // + iBar.Clean(); + } + + // + // Validating Block Length Based on Direction ... + if (result && + validations.minAllowedBlockLength) + { + // + count = 0; + fromIDX = triggerBlock.FromIndex(); + int sIDX = fromIDX; + has = true; + while (has) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + sIDX // + ); + + // + has = + has && + (isBullish + ? iBar.low > triggerBlock.trigger.lower + : iBar.high < triggerBlock.trigger.upper); + + // + if (!has) + { + break; + } + + // + sIDX++; + count++; + iBar.Clean(); + } + + // + result = + iBar.IsValid() && + count >= validations.minAllowedBlockLength; + if (result) + { + // + // Update Trigger Block ... + bool usaMinAllowedForBlockLength = false; + if (usaMinAllowedForBlockLength) + { + fromIDX = fromIDX + validations.minAllowedBlockLength; + } + else + { + fromIDX = sIDX - 1; + } + + // + triggerBlock.trigger.from = GetBarTime( + conditions.symbol, + conditions.period, + fromIDX // + ); + } + + // + iBar.Clean(); + } + + // + if (!result) + { + triggerBlock.Clean(); + } + + // + // Summarize result ... + result = triggerBlock.IsValid(); + + // + // Cleanup Resources ... + + // + iBar.Clean(); + + // + if (!result) + { + // + conditions.Clean(); + triggerBlock.Clean(); + } + + // + return result; +} + +/** + * Filter a Trigger Block ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param triggerBlock: XTriggerBlock Refrence, Trigger Block ... + * @param conditions: X121XCatbConditions Refrence, Trigger Block Conditions ... + * @param filters: XTriggerBlockFilters Refrence, Provides Trigger Block Filters ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Conditions reading ... + * + * @return ( bool ) + */ +bool FilterTriggerBlock( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockFilters &filters, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Checking Conditions ... + + // + // Normalize Args ... + conditions.Clean(); + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 0); + + // + // Validate Args ... + result = + helper != NULL && + barAnalyser != NULL && + triggerBlock.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Market Conditions ... + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + XOHCL iBar; + int toIDX = -1; + int fromIDX = -1; + bool has = false; + bool isBullish = triggerBlock.IsBullish(); + bool isBearish = triggerBlock.IsBearish(); + double points = GetPoints(triggerBlock.ob.symbol); + ENUM_X_DIRECTION iDir = triggerBlock.GetDirection(); + + // + // Checking Conditions ... + + // + // Filter Based KI ... + if (result && + filters.filterBasedOnKI) + { + // + int count = 0; + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + double lKI = conditions.kiBuffer[zIDX]; + for (int i = toIDX; i < fromIDX; i++) + { + // + double iKI = helper.GetKI(i); + if (iKI == lKI) + { + count++; + } + else + { + break; + } + } + + // + result = count >= 3; + } + + // + // Filter Based On PV ... + if (result && + filters.filterBasedOnPV) + { + // + // For PV Filtering ... + + // + // Detect BOS ... + + // + // When Loopback for BOS has Specified Value ... + // we Lookup for BOS on Specific Period ... + if (filters.bosLoopback > 0) + { + // + has = true; + int fBOSIDX = -1; + int rBOSIDX = -1; + bool isBOS = false; + bool isFBOS = false; + bool isRBOS = false; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + int sIDX = fromIDX; + while (has) + { + // + double iPeak = helper.GetPeak(sIDX); + double iPPeak = helper.GetPeak(sIDX + 1); + + // + double iVale = helper.GetVale(sIDX); + double iPVale = helper.GetVale(sIDX + 1); + + // + isPeakOverLast = + iPeak > 0 && + iPeak > iPPeak; + + // + isValeUnderLast = + iVale > 0 && + iVale < iPVale; + + // + isFBOS = + isBullish + ? isPeakOverLast + : isValeUnderLast; + if (isFBOS) + { + fBOSIDX = sIDX; + } + + // + isRBOS = + isBullish + ? isValeUnderLast + : isPeakOverLast; + if (isRBOS) + { + rBOSIDX = sIDX; + } + + // + isBOS = + (isBullish && + isPeakOverLast) || + (isBearish && + isValeUnderLast); + if (isBOS) + { + break; + } + + // + sIDX++; + has = !isBOS && + sIDX < fromIDX + filters.bosLoopback; + } + + // + isFBOS = IsValidIndex(fBOSIDX); + isRBOS = IsValidIndex(rBOSIDX); + + // + result = isBOS && + isFBOS && + !isRBOS; + } + + // + // When Loopback for BOS has not Specified Value ... + // we Lookup for BOS on GAP End Bar ... + if (filters.bosLoopback <= 0) + { + // + toIDX = triggerBlock.ToIndex(); + + // + // Initialize iBar ... + result = iBar.Init( + conditions.symbol, + conditions.period, + toIDX // + ); + result = + result && + (isBullish ? iBar.high > helper.GetPeak(toIDX + 1) + : iBar.low < helper.GetVale(toIDX + 1)); + } + } + + // + // Filter Based on SAR ... + if (result && + filters.filterBasedOnSar) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + + // + double iSarState = helper.GetSarState(toIDX); + double iPSarState = helper.GetSarState(toIDX + 1); + + // + double iFSarState = helper.GetSarState(fromIDX); + double iPFSarState = helper.GetSarState(fromIDX + 1); + + // + bool isSarBullish = + iSarState > 0; + + // + bool isSarBearish = + iSarState < 0; + + // + bool isFSarBullish = + iFSarState > 0; + + // + bool isFSarBearish = + iFSarState < 0; + + // + bool isSarSwitchedToBullish = + iSarState > 0 && + iPSarState <= 0; + + // + bool isSarSwitchedToBearish = + iSarState < 0 && + iPSarState >= 0; + + // + bool isFSarSwitchedToBullish = + iFSarState > 0 && + iPFSarState <= 0; + + // + bool isFSarSwitchedToBearish = + iFSarState < 0 && + iPFSarState >= 0; + + // + // Check SAR Direction ... + + // + if (result && + !filters.forceSarSwitched) + { + // + result = isBullish + ? isSarBullish + : isSarBearish; + } + + // + if (result && + filters.forceSarSwitched) + { + // + result = isBullish + ? isSarSwitchedToBullish + : isSarSwitchedToBearish; + } + + // + if (result && + filters.forceSarOnBothSide) + { + // + if (result && + !filters.forceSarSwitched) + { + // + result = isBullish + ? isFSarBullish + : isFSarBearish; + } + + // + if (result && + filters.forceSarSwitched) + { + // + result = isBullish + ? isFSarSwitchedToBullish + : isFSarSwitchedToBearish; + } + } + + // + // Check Sar Has Reversal Direction inside Trigger Block ... + if (result && + filters.forceSarHasReversalSide) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + double iSarState = helper.GetSarState(i); + + // + has = + isBullish + ? iSarState > 0 + : iSarState < 0; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Force Sar Breakouts ... + // in this Senario Sar must in following Direction and + // there is not any Switches ... + // but must breakout Bar the last in Reversal Direction + // of Sar ... + if (result && + filters.forceSarHasBreakout) + { + // + bool isSarBullishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isSarBearishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + result = + isBullish + ? isSarBullishStart + : isSarBearishStart; + } + } + + // + // Filter Based On RSI ... + if (result && + filters.filterBasedOnRSI) + { + // + // Here We Can Apply RSI Filters ... + // Since RSI Filters must be Check on FVG Bars ... + // we Have to Loop back Based on FVG Bars to Detect Conditions ... + double rsiTrend = (conditions.rsiOBLevel + conditions.rsiOSLevel) / 2; + + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + + // + // Filter Using RSI Trending ... + if (result && + filters.forceHasRSITrending) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iRSI = helper.GetRSI(i); + double iPRSI = helper.GetRSI(i + 1); + + // + has = + (isBullish + ? (iRSI > rsiTrend && + iRSI > iPRSI) + : (iRSI < rsiTrend && + iRSI < iPRSI)); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using RSI V Pattern ... + if (result && + filters.forceHasRSIVPattern) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iRSI = helper.GetRSI(i); + double iPRSI = helper.GetRSI(i + 1); + double iP2RSI = helper.GetRSI(i + 2); + + // + bool isRSIVBullish = + iRSI > iPRSI && + iP2RSI > iPRSI; + + // + bool isRSIVBearish = + iRSI < iPRSI && + iP2RSI < iPRSI; + + // + has = + (isBullish + ? isRSIVBullish + : isRSIVBearish); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using RSI Crossing on OB/OS Levels ... + if (result && + filters.forceHasRSICrossing) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iRSI = helper.GetRSI(i); + double iPRSI = helper.GetRSI(i + 1); + + // + bool isRSICrossedOverOS = + iRSI > conditions.rsiOSLevel && + iPRSI <= conditions.rsiOSLevel; + + // + bool isRSICrossedUnderOB = + iRSI < conditions.rsiOBLevel && + iPRSI >= conditions.rsiOBLevel; + + // + has = + (isBullish + ? isRSICrossedOverOS + : isRSICrossedUnderOB); + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Based On ADX ... + if (result && + filters.filterBasedOnADX) + { + // + // Here We Can Apply ADX Filters ... + // Since ADX Filters must be Check on FVG Bars ... + // we Have to Loop back Based on FVG Bars to Detect Conditions ... + + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + + // + // Filter Using ADX Trending ... + if (result && + filters.forceHasADXTrending) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iADX = helper.GetADX(i); + double iPADX = helper.GetADX(i + 1); + + // + has = iADX > conditions.adxThreshold && + iADX > iPADX; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using ADX Crossing on +DI/-DI ... + if (result && + filters.forceHasADXCrossing) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iDIPlus = helper.GetADXP(i); + double iPDIPlus = helper.GetADXP(i + 1); + + // + double iDIMinus = helper.GetADXN(i); + double iPDIMinus = helper.GetADXN(i + 1); + + // + bool isADXPlusCrossedOverMinus = + iDIPlus > iDIMinus && + iPDIPlus <= iDIMinus; + + // + bool isADXMinusCrossedOverPlus = + iDIMinus > iDIPlus && + iPDIMinus <= iDIPlus; + + // + has = + isBullish + ? isADXPlusCrossedOverMinus + : isADXMinusCrossedOverPlus; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Based On ATR Band ... + if (result && + filters.filterBasedOnATR) + { + // + // Here We Can Apply ATR Filters ... + // Since ATR Filters must be Check on OB Bars ... + // we Have to Loop back Based on OB Bars to Detect Conditions ... + + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + // Filter Using ATR Trending ... + if (result && + filters.forceHasATRTrending) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iATRUpper = helper.GetATRUpper(i); + double iPATRUpper = helper.GetATRUpper(i + 1); + + // + double iATRLower = helper.GetATRLower(i); + double iPATRLower = helper.GetATRLower(i + 1); + + // + bool isATRUp = + iATRLower > iPATRLower; + + // + bool isATRDown = + iATRUpper < iPATRUpper; + + // + has = isBullish + ? isATRUp + : isATRDown; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using ATR Breakout ... + if (result && + filters.forceHasATRBreakout) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iATRUpper = helper.GetATRUpper(i); + double iATRLower = helper.GetATRLower(i); + + // + has = isBullish + ? triggerBlock.ob.lower < iATRLower + : triggerBlock.ob.upper > iATRUpper; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Based On Trend ... + if (result && + filters.filterBasedOnTrend) + { + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + + // + // Filter Using Trend Direction ... + if (result && + filters.forceHasTrendDir) + { + // + result = + result && + isBullish + ? conditions.isTrendBullish + : conditions.isTrendBearish; + } + + // + // Filter Using Trend Direction On Both Side ... + if (result && + filters.forceHasTrendDirOnBothSide) + { + // + // Side To ... + result = + result && + isBullish + ? conditions.isTrendBullish + : conditions.isTrendBearish; + + // + // Side From ... + int sFIDX = triggerBlock.ob.FromIndex(); + double sFTrendState = helper.GetTrendState(sFIDX); + result = + result && + isBullish + ? sFTrendState > 0 + : sFTrendState < 0; + } + + // + // Filter Using Trend Change ... + if (result && + filters.forceHasTrendChange) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iTrendState = helper.GetTrendState(i); + double iPTrendState = helper.GetTrendState(i + 1); + + // + bool isTrendSwitchedToBullish = + iTrendState > 0 && + iPTrendState <= 0; + + // + bool isTrendSwitchedToBearish = + iTrendState < 0 && + iPTrendState >= 0; + + // + has = + isBullish + ? isTrendSwitchedToBullish + : isTrendSwitchedToBearish; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Trend Trending ... + if (result && + filters.forceHasTrendTrending) + { + // + result = + result && + (isBullish + ? conditions.trendBuffer[cIDX] > conditions.trendBuffer[pIDX] + : conditions.trendBuffer[cIDX] < conditions.trendBuffer[pIDX]); + } + + // + // Filter Using Trend Rejection ... + if (result && + filters.forceHasTrendRejection) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + + // + // Read Trend Value ... + double iTrend = helper.GetTrend(i); + + // + bool isTrendBullishRejected = + has && + iBar.low < iTrend && + iBar.GetDown() > iTrend; + + // + bool isTrendBearishRejected = + has && + iBar.high > iTrend && + iBar.GetUp() < iTrend; + + // + has = + has && + (isBullish + ? isTrendBullishRejected + : isTrendBearishRejected); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Trend Inside ... + if (result && + filters.forceHasTrendLineInside) + { + // + result = + result && + conditions.trendBuffer[cIDX] > triggerBlock.ob.lower && + conditions.trendBuffer[cIDX] < triggerBlock.ob.upper; + } + + // + // Filter Using Trend Place ... + if (result && + filters.forceHasTrendPlace) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + double mult = + isBullish + ? 1 + : -1; + double edge = isBullish + ? triggerBlock.ob.lower + : triggerBlock.ob.upper; + double factor = edge + (mult * (triggerBlock.ob.GetRange() / 4)); + for (int i = toIDX; i < fromIDX; i++) + { + // + double iTrend = helper.GetTrend(i); + + // + has = + isBullish + ? factor >= iTrend + : factor <= iTrend; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Using Delta ... + if (result && + filters.filterBasedOnDelta) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iDelta = helper.GetDelta(i); + double iPDelta = helper.GetDelta(i + 1); + + // + double iDeltaSignal = helper.GetDeltaSignal(i); + double iPDeltaSignal = helper.GetDeltaSignal(i + 1); + + // + bool isDeltaUp = + iDelta > iPDelta; + + // + bool isDeltaDown = + iDelta < iPDelta; + + // + bool isDeltaSignalUp = + iDeltaSignal > iPDeltaSignal; + + // + bool isDeltaSignalDown = + iDeltaSignal < iPDeltaSignal; + + // + bool isDeltaCrossedOverSignal = + iDelta > iDeltaSignal && + iPDelta <= iPDeltaSignal; + + // + bool isDeltaCrossedUnderSignal = + iDelta < iDeltaSignal && + iPDelta >= iPDeltaSignal; + + // + has = + isBullish + ? (isDeltaUp && + isDeltaSignalUp && + isDeltaCrossedOverSignal) + : (isDeltaDown && + isDeltaSignalDown && + isDeltaCrossedUnderSignal); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Volume ... + if (result && + filters.filterBasedOnVolume) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iBullVolume = helper.GetBullishVolume(i); + double iPBullVolume = helper.GetBullishVolume(i + 1); + + // + double iBullVolumeSignal = helper.GetBullishVolumeSignal(i); + double iPBullVolumeSignal = helper.GetBullishVolumeSignal(i + 1); + + // + double iBearVolume = helper.GetBearishVolume(i); + double iPBearVolume = helper.GetBearishVolume(i + 1); + + // + double iBearVolumeSignal = helper.GetBearishVolumeSignal(i); + double iPBearVolumeSignal = helper.GetBearishVolumeSignal(i + 1); + + // + bool isBullVolumeUp = + iBullVolume > iPBullVolume; + + // + bool isBullVolumeSignalUp = + iBullVolumeSignal > iPBullVolumeSignal; + + // + bool isBearVolumeUp = + iBearVolume > iPBearVolume; + + // + bool isBearVolumeSignalUp = + iBearVolumeSignal > iPBearVolumeSignal; + + // + bool isVolumeSwitchedToBullish = + iBullVolumeSignal > iBearVolumeSignal && + iPBullVolumeSignal <= iPBearVolumeSignal; + + // + bool isVolumeSwitchedToBearish = + iBearVolumeSignal > iBullVolumeSignal && + iPBearVolumeSignal <= iPBullVolumeSignal; + + // + has = + isBullish + ? (isBullVolumeUp && + isBullVolumeSignalUp && + isVolumeSwitchedToBullish) + : (isBearVolumeUp && + isBearVolumeSignalUp && + isVolumeSwitchedToBearish); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Signal Bar ... + if (result && + filters.filterBasedOnSignalBar) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + double iSOpen = helper.GetSBarOpen(toIDX); + double iPSOpen = helper.GetSBarOpen(toIDX + 1); + + // + double iSClose = helper.GetSBarClose(toIDX); + double iPSClose = helper.GetSBarClose(toIDX + 1); + + // + double iSPow = MathAbs(iSOpen - iSClose); + double iPSPow = MathAbs(iPSOpen - iPSClose); + + // + result = + result && + iSPow > iPSPow && + (isBullish + ? iSClose > iSOpen + : iSClose < iSOpen); + + // + // Now Looking for Dir Change ... + if (result) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + iSOpen = helper.GetSBarOpen(toIDX); + iPSOpen = helper.GetSBarOpen(toIDX + 1); + + // + iSClose = helper.GetSBarClose(toIDX); + iPSClose = helper.GetSBarClose(toIDX + 1); + + // + bool isSBullish = + iSClose > iSOpen; + + // + bool isPSBullish = + iPSClose > iPSOpen; + + // + bool isSBearish = + iSClose < iSOpen; + + // + bool isPSBearish = + iPSClose < iPSOpen; + + // + bool isSSwitchedToBullish = + isSBullish && + !isPSBullish; + + // + bool isSSwitchedToBearish = + isSBearish && + !isPSBearish; + + // + has = + isBullish + ? isSSwitchedToBullish + : isSSwitchedToBearish; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Using Signal Bar ... + if (result && + filters.filterBasedOnHKSignalBar) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + double iSOpen = helper.GetHKSBarOpen(toIDX); + double iPSOpen = helper.GetHKSBarOpen(toIDX + 1); + + // + double iSClose = helper.GetHKSBarClose(toIDX); + double iPSClose = helper.GetHKSBarClose(toIDX + 1); + + // + double iSPow = MathAbs(iSOpen - iSClose); + double iPSPow = MathAbs(iPSOpen - iPSClose); + + // + result = + result && + iSPow > iPSPow && + (isBullish + ? iSClose > iSOpen + : iSClose < iSOpen); + + // + // Now Looking for Dir Change ... + if (result) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + iSOpen = helper.GetHKSBarOpen(toIDX); + iPSOpen = helper.GetHKSBarOpen(toIDX + 1); + + // + iSClose = helper.GetHKSBarClose(toIDX); + iPSClose = helper.GetHKSBarClose(toIDX + 1); + + // + bool isSBullish = + iSClose > iSOpen; + + // + bool isPSBullish = + iPSClose > iPSOpen; + + // + bool isSBearish = + iSClose < iSOpen; + + // + bool isPSBearish = + iPSClose < iPSOpen; + + // + bool isSSwitchedToBullish = + isSBullish && + !isPSBullish; + + // + bool isSSwitchedToBearish = + isSBearish && + !isPSBearish; + + // + has = + isBullish + ? isSSwitchedToBullish + : isSSwitchedToBearish; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + if (!result) + { + triggerBlock.Clean(); + } + + // + // Summarize result ... + result = triggerBlock.IsValid(); + + // + // Cleanup Resources ... + + // + iBar.Clean(); + + // + if (!result) + { + // + conditions.Clean(); + triggerBlock.Clean(); + } + + // + return result; +} + +// +void ValidateTriggerBlockLiquidities( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockValidationRules &validations // +) +{ + // + bool has = false; + + // + has = + helper != NULL && + barAnalyser != NULL && + triggerBlock.IsValid() && + (triggerBlock.fLiquidity.IsValid() || + triggerBlock.rLiquidity.IsValid()); + if (!has) + { + return; + } + + // + bool hasFLiq = triggerBlock.fLiquidity.IsValid(); + bool hasRLiq = triggerBlock.rLiquidity.IsValid(); + + // + // TODO: Implement Liquidity Validation ... +} + +// +// Draw Specific Trigger Block ... +bool DrawTriggerBlock( + XTriggerBlock &trigger, + XCPOIDrawer *drawer, + CArrayObj &objects, + datetime to = NULL, + // + bool _drawSignals = false, + int rrZoneLength = 10, + // Styles ... + // + // Trigger Block ... + int tbWidth = 1, // Trigger Block Width + color tbBullishColor = clrAqua, // Trigger Block Bullish Color + color tbBearishColor = clrMagenta, // Trigger Block Bearish Color + ENUM_LINE_STYLE tbStyle = STYLE_DASHDOTDOT, // Trigger Block Style + // + // OB ... + int obWidth = 1, // OB Width + color obBullishColor = clrLime, // OB Bullish Color + color obBearishColor = clrRed, // OB Bearish Color + ENUM_LINE_STYLE obStyle = STYLE_DOT, // OB Style + // + // FVG ... + int fvgWidth = 2, // FVG Width + color fvgBullishColor = clrLime, // FVG Bullish Color + color fvgBearishColor = clrRed, // FVG Bearish Color + ENUM_LINE_STYLE fvgStyle = STYLE_SOLID // FVG Style +) +{ + // + bool result = false; + + // + // Validate Args ... + result = trigger.IsValid() && + drawer != NULL; + if (!result) + { + return result; + } + + // + XTriggerBlock _trigger = trigger; + + // + // Update To ... + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + // + _trigger.trigger.to = to; + _trigger.rLiquidity.to = to; + _trigger.fLiquidity.to = to; + } + + // + bool isBullish = _trigger.IsBullish(); + + // + // Draw OB ... + if (_trigger.ob.IsValid()) + { + // + XCBoxObject *iOBObj; + result = drawer.DrawBox( + _trigger.ob, + iOBObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? obBullishColor + : obBearishColor; + + // + iOBObj.BoxColor(iClr); + iOBObj.BoxWidth(obWidth); + iOBObj.BoxStyle(obStyle); + + // + // Store Object ... + objects.Add(iOBObj); + } + ZeroMemory(iOBObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw FVG ... + if (_trigger.fvg.IsValid()) + { + // + XCBoxObject *iFVGObj; + result = drawer.DrawBox( + _trigger.fvg, + iFVGObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? fvgBullishColor + : fvgBearishColor; + + // + iFVGObj.BoxColor(iClr); + iFVGObj.BoxWidth(fvgWidth); + iFVGObj.BoxStyle(fvgStyle); + + // + // Store Object ... + objects.Add(iFVGObj); + } + ZeroMemory(iFVGObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Trigger ... + if (_trigger.trigger.IsValid()) + { + // + XCBoxObject *iTriggerObj; + result = drawer.DrawBox( + _trigger.trigger, + iTriggerObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? tbBullishColor + : tbBearishColor; + + // + iTriggerObj.BoxColor(iClr); + iTriggerObj.BoxWidth(tbWidth); + iTriggerObj.BoxStyle(tbStyle); + + // + // Store Object ... + objects.Add(iTriggerObj); + } + ZeroMemory(iTriggerObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Liquidities ... + + // + // Reversla Liquidity ... + if (_trigger.rLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + _trigger.rLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Following Liquidity ... + if (_trigger.fLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + _trigger.fLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Swing Bar ... + if (_trigger.swingBar.IsValid()) + { + // + color swingColor = + _trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + ENUM_X_PRICE swingPType = + _trigger.fvg.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *swingObj; + result = drawer.CreateBarArrow( + _trigger.swingBar, + swingObj, + swingPType, + 159, + swingColor // + ); + if (result) + { + objects.Add(swingObj); + } + ZeroMemory(swingObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw RR of Signal ... + if (_drawSignals && + _trigger.signal.IsValid() && + rrZoneLength > 0) + { + // + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + result = iRRObj.Create( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + _trigger.signal, + rrZoneLength // + ); + if (result) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + objects.Add(iRRObj); + } + ZeroMemory(iRRObj); + + // + if (result) + { + return result; + } + } + + // + return result; +} diff --git a/BKPS/14040626/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 b/BKPS/14040626/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 new file mode 100644 index 0000000..ebda6e9 --- /dev/null +++ b/BKPS/14040626/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 @@ -0,0 +1,1650 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// --------------------------------------- +// Name: XCATBEASignallerLib +// Description: required Parsers for XCATBEA Signaller ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" +#include "../Classes/xcatbea.x-poi.detector.class.mq5" +#include "../Classes/xcatbea.x-poi.drawer.class.mq5" +#include "../Libraries/xcatbea.lib.mq5" + +// +// Definitions ... + +// +struct XCATBEAStrategyConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Setup Props ... + + // + double sl; + double tp; + double pivot; + double point; + double entry; + double reward; + string provider; + + // + XTarget targets[]; + + // + datetime time; + datetime setupTime; + datetime triggerTime; + + // + XBoxZone pivotZone; + ENUM_X_DIRECTION dir; + XTriggerBlock triggerBlock; + ENUM_X_POSITION_TYPES type; + X121XCatbConditions conditions; + + // + // Constructor ... + XCATBEAStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + tp = 0; + pivot = 0; + point = 0; + entry = 0; + reward = 0; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + time = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + SpecifiedClean(targets); + + // + pivotZone.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + ZeroMemory(this); + } + + // + // Signalling ... + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check Conditions Has Valid Bullish Signal ... + * + * @return ( bool ) + */ + bool HasBullishSignal() + { + // + bool result = false; + + // + result = + (sl > 0 || + tp > 0) && + IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + result = + IsBullish(dir); + + // + return result; + } + + /** + * Check Conditions Has Valid Bearish Signal ... + * + * @return ( bool ) + */ + bool HasBearishSignal() + { + // + bool result = false; + + // + result = + (sl > 0 || + tp > 0) && + IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + result = + IsBearish(dir); + + // + return result; + } + + // + // Setting Up and Triggering Up ... + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsSpecifiedValid(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 && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // +}; + +/** + * Converts Strategy Conditions to Signal ... + */ +bool ToSignal( + XSignal &signal, + XCATBEAStrategyConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + signal.Clean(); + + // + // Validate Args ... + result = + conditions.IsValid() && + conditions.IsSetuped() && + conditions.CanTrigger(); + if (!result) + { + return result; + } + + // + // Do Converting ... + signal.volume = 0.01; + signal.tp = conditions.tp; + signal.sl = conditions.sl; + signal.entry = conditions.entry; + signal.symbol = conditions.symbol; + signal.period = conditions.period; + signal.mode = X_ORDER_MODE_MARKET; + signal.time = conditions.triggerTime; + signal.provider = conditions.provider; + signal.type = conditions.type == + X_POSITION_TYPE_LONG + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + signal.conditions = conditions + .conditions + .GenerateSummary( + false, + true, + true, + false // Ignore False Conditions ... + ); + Copy( + conditions.targets, + signal.targets // + ); + + // + // Validate Result ... + result = signal.IsValid(); + + // + return result; +} + +/** + * Detect Signal Zone based on Market Conditions ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param conditions: X121XCatbConditions instance reference, hold signalling Conditions ... + * @param signalZone: XBoxZone instance reference, hold Signal Zone ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Market Conditions ... + * + * @return ( bool ) + */ +bool DetectSignalZone( + XCX121XCatbHelper *helper, + XCXCATBEAPOIDrawer *drawer, + XCXCATBEAPOIDetector *detector, + XCBarAnalyser *barAnalyser, + X121XCatbConditions &conditions, + XBoxZone &signalZone, + bool allowSignallingConditions1 = false, + bool allowSignallingConditions2 = false, + bool allowSignallingConditions3 = false, + bool allowSignallingConditions4 = false, + bool allowSignallingConditions5 = false, + bool allowSignallingConditions6 = false, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + signalZone.Clean(); + conditions.Clean(); + loopback = NormalizeInt(loopback, 0); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Args ... + result = + helper != NULL && + detector != NULL && + barAnalyser != NULL; + if (!result) + { + return result; + } + + // + // Try to Recieve Conditions of Market ... + + // + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + int idx = -1; + bool has = false; + bool isBullish = false; + bool isBearish = false; + double bullishScore = 0; + double bearishScore = 0; + + // + double iUpper = 0; + double iLower = 0; + string iType = NULL; + datetime iTo = NULL; + string iSymbol = NULL; + datetime iFrom = NULL; + int longPushers = 0; + int shortPushers = 0; + ENUM_TIMEFRAMES iPeriod = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Signalling ... + if (result) + { + // + iSymbol = conditions.symbol; + iPeriod = conditions.period; + + // + // Looking For Conditions ... + + // + // Reading Values ... + + // + // Readng Scores ... + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + // Prepared Conditions ... + + // + // SCORES ... + bool isScoreBullish = bullishScore > bearishScore; + bool isScoreBearish = bearishScore > bullishScore; + + // + // SAR ... + + // + bool isSarBullishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isSarBearishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + // TREND ... + + // + bool isTrendBullishStart = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBullish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBearish.IsValid() && + // + // Current Close is Over previous ... + conditions.bars[cIDX].close > helper.lastTrendBearish.after && + // + // Before close is not Over previous ... + conditions.bars[pIDX].close <= helper.lastTrendBearish.after + // + ) + // + ; + + // + bool isTrendBearishStart = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBearish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastTrendBullish.after && + // + // Before close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastTrendBullish.after + // + ) + // + ; + + // + // ADX ... + + // + bool isADXBullishStart = + // + ( + // + // ADX Value is Switched to Strong ... + conditions.adxBuffer[cIDX] > conditions.adxThreshold && + conditions.adxBuffer[pIDX] <= conditions.adxThreshold && + // + // ADX must Up ... + conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && + // + // ADX +DI is Bigger than -DI ... + conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX] && + // + // ADX +DI is Up ... + conditions.adxpBuffer[cIDX] > conditions.adxpBuffer[pIDX] + // + ) + // + ; + + // + bool isADXBearishStart = + // + ( + // + // ADX Value is Switched to Strong ... + conditions.adxBuffer[cIDX] > conditions.adxThreshold && + conditions.adxBuffer[pIDX] <= conditions.adxThreshold && + // + // ADX must Up ... + conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && + // + // ADX -DI is Bigger than +DI ... + conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX] && + // + // ADX -DI is Up ... + conditions.adxnBuffer[cIDX] > conditions.adxnBuffer[pIDX] + // + ) + // + ; + + // + // DELTA ... + + // + bool isDeltaBullishStart = + // + // Check State ... + ( + // + // Delta is Up ... + conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Over Delta Signal ... + conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastDeltaBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastDeltaBearish.after + // + ; + + // + bool isDeltaBearishStart = + // + // Check State ... + ( + // + // Delta is Down ... + conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBullish.IsValid() && + // + // Current Close is Under last ... + conditions.bars[cIDX].close < helper.lastDeltaBullish.after && + // + // Before Close is not Under last ... + conditions.bars[pIDX].close >= helper.lastDeltaBullish.after + // + ; + + // + // VOLUME ... + + // + bool isVolumeBullishStart = + // + ( + // + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastVolumeBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastVolumeBearish.after + // + ; + + // + bool isVolumeBearishStart = + // + ( + // + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBullish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close < helper.lastVolumeBullish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close >= helper.lastVolumeBullish.after + // + ; + + // + // SIGNAL Bar ... + + // + bool isSBarBullishStart = + // + ( + // + // Check Direction ... + conditions.isSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after + // + ) + // + ; + + // + bool isSBarBearishStart = + // + ( + // + // Check Direction ... + conditions.isSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after + // + ) + // + ; + + // + // HKSIGNAL Bar ... + + // + bool isHKSBarBullishStart = + // + ( + // + // Check Direction ... + conditions.isHKSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after + // + ) + // + ; + + // + bool isHKSBarBearishStart = + // + ( + // + // Check Direction ... + conditions.isHKSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after + // + ) + // + ; + + // + // Detect Bar Verifications ... + + // + ENUM_X_DIRECTION iBDir; + + // + // Rejected ... + bool isRejected = + barAnalyser + .IsRejected( + conditions.bars[cIDX], + iBDir // + ); + bool isBullishRejected = + isRejected && + IsBullish(iBDir); + bool isBearishRejected = + isRejected && + IsBearish(iBDir); + + // + // Engulfed ... + bool isEngulfed = + barAnalyser + .IsEngulfed( + conditions.bars[cIDX], + iBDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iBDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iBDir); + + // + // Momentum ... + bool isMomentum = + barAnalyser + .IsMomentum( + conditions.bars[cIDX], + iBDir // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iBDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iBDir); + + // + bool isTriggerBar = barAnalyser + .IsValidForTrigger( + conditions.bars[0], + iBDir, + true, // Allow Cond 1 ... + true, // Allow Cond 2 ... + true, // Allow Cond 3 ... + true, // Allow Cond 4 ... + true, // Allow Cond 5 ... + true, // Allow Cond 6 ... + true // Allow Cond 7 ... + // + ); + bool isBullishTriggerBar = + isTriggerBar && + IsBullish(iBDir); + bool isBearishTriggerBar = + isTriggerBar && + IsBearish(iBDir); + + // + bool isBarBullishPressured = + isBullishRejected || + isBullishEngulfed || + isBullishMomentum || + isBullishTriggerBar; + + // + bool isBarBearishPressured = + isBearishRejected || + isBearishEngulfed || + isBearishMomentum || + isBearishTriggerBar; + + // + // Implement Signalling Conditions ... + + // + // -------------- + // Conditions 1: + // -------------- + // Descriptions: + // - [] Detect Parabolic Sar Direction Change ... + // - [] KI is Directional ... + // - [] Bar Has Pressured ... + // - [] ATR is Directional Up/Down ... + // - [] TREND is Directional ... + // - [] TREND is Directional Change ... + // - [] TREND is Directional Up/Down ... + // ------------------------------------ + + // + bool isCond1Bullish = false; + bool isCond1Bearish = false; + if (allowSignallingConditions1) + { + // + isCond1Bullish = + // + // Start ... + (isSarBullishStart && + !isSarBearishStart) && + // + // SCORE ... + isScoreBullish && + // + // BAR ... + isBarBullishPressured && + // + // KI ... + // conditions.isKIUp && + conditions.isKIBullish && + // + // ATR ... + conditions.isATRUp && + // + // TREND ... + isTrendBullishStart && + conditions.isTrendUp && + conditions.isTrendBullish + // + ; + + // + isCond1Bearish = + // + // Start ... + (isSarBearishStart && + !isSarBullishStart) && + // + // SCORE ... + isScoreBearish && + // + // BAR ... + isBarBearishPressured && + // + // KI ... + // conditions.isKIDown && + conditions.isKIBearish && + // + // ATR ... + conditions.isATRDown && + // + // TREND ... + isTrendBearishStart && + conditions.isTrendDown && + conditions.isTrendBearish + // + ; + } + + // + bool isCond1 = + isCond1Bullish || + isCond1Bearish; + if (isCond1) + { + // + // Generate Direction Shift Zone ... + has = GenerateSarDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + + // + if (isCond1Bullish) + { + longPushers++; + } + else + { + shortPushers++; + } + } + // ---------------------------------- + + // + // -------------- + // Conditions 2: + // -------------- + // Descriptions: + // - [] Detect Trend Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + // Descriptions: + // - [] + // ------------------------------------ + + // + bool isCond2Bullish = false; + bool isCond2Bearish = false; + if (allowSignallingConditions2) + { + // // + // isCond2Bullish = + // // + // // Start ... + // (isTrendBullishStart && + // !isTrendBearishStart) + // // + // ; + + // // + // isCond2Bearish = + // // + // // Start ... + // (isTrendBearishStart && + // !isTrendBullishStart) + // // + // ; + + // + // Temp Cndition 2 ... + + // + // Bullish ... + isCond2Bullish = + isScoreBullish && + isBullishTriggerBar && + conditions.isKIBullish && + conditions.isSarSwitchedToBullish; + // isScoreBullish && + // isBarBullishPressured && + // conditions.isKISwitchedToBullish && + // conditions.isSarSwitchedToBullish; + + // + // Bearish ... + isCond2Bearish = + isScoreBearish && + isBearishTriggerBar && + conditions.isKIBearish && + conditions.isSarSwitchedToBearish; + // isScoreBearish && + // isBarBearishPressured && + // conditions.isKISwitchedToBearish && + // conditions.isSarSwitchedToBearish; + } + + // + bool isCond2 = + isCond2Bullish || + isCond2Bearish; + if (isCond2) + { + // + // Retireve Conditions 2 ... + Print("Condition 2 Happens ..."); + + // + // Generate Direction Shift Zone ... + has = GenerateTrendDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + + // + if (isCond2Bullish) + { + longPushers++; + } + else + { + shortPushers++; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 3: + // -------------- + // Descriptions: + // - [] Detect Delta Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond3Bullish = false; + bool isCond3Bearish = false; + if (allowSignallingConditions3) + { + // + isCond3Bullish = + // + // Start ... + (isDeltaBullishStart && + !isDeltaBearishStart) + // + ; + + // + isCond3Bearish = + // + // Start ... + (isDeltaBearishStart && + !isDeltaBullishStart) + // + ; + } + + // + bool isCond3 = + isCond3Bullish || + isCond3Bearish; + if (isCond3) + { + // + // Generate Direction Shift Zone ... + has = GenerateDeltaDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + + // + if (isCond3Bullish) + { + longPushers++; + } + else + { + shortPushers++; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 4: + // -------------- + // Descriptions: + // - [] Detect Volume Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond4Bullish = false; + bool isCond4Bearish = false; + if (allowSignallingConditions4) + { + // + isCond4Bullish = + // + // Start ... + (isVolumeBullishStart && + !isVolumeBearishStart) + // + ; + + // + isCond4Bearish = + // + // Start ... + (isVolumeBearishStart && + !isVolumeBullishStart) + // + ; + } + + // + bool isCond4 = + isCond4Bullish || + isCond4Bearish; + if (isCond4) + { + // + // Generate Direction Shift Zone ... + has = GenerateVolumeDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + + // + if (isCond4Bullish) + { + longPushers++; + } + else + { + shortPushers++; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 5: + // -------------- + // Descriptions: + // - [] Detect Signal Bar Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond5Bullish = false; + bool isCond5Bearish = false; + if (allowSignallingConditions5) + { + // + isCond5Bullish = + // + // Start ... + (isSBarBullishStart && + !isSBarBearishStart) + // + ; + + // + isCond5Bearish = + // + // Start ... + (isSBarBearishStart && + !isSBarBullishStart) + // + ; + } + + // + bool isCond5 = + isCond5Bullish || + isCond5Bearish; + if (isCond5) + { + // + // Generate Direction Shift Zone ... + has = GenerateSignalBarDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + + // + if (isCond5Bullish) + { + longPushers++; + } + else + { + shortPushers++; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 6: + // -------------- + // Descriptions: + // - [] Detect HK Signal Bar Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond6Bullish = false; + bool isCond6Bearish = false; + if (allowSignallingConditions6) + { + // + isCond6Bullish = + // + // Start ... + (isHKSBarBullishStart && + !isHKSBarBearishStart) + // + ; + + // + isCond6Bearish = + // + // Start ... + (isHKSBarBearishStart && + !isHKSBarBullishStart) + // + ; + } + + // + bool isCond6 = + isCond6Bullish || + isCond6Bearish; + if (isCond6) + { + // + // Generate Direction Shift Zone ... + has = GenerateHKSignalBarDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + + // + if (isCond6Bullish) + { + longPushers++; + } + else + { + shortPushers++; + } + } + // ------------------------------------ + + // + // Summarizing Signalling Results ... + + // + isBullish = + // + isCond1Bullish || + isCond2Bullish || + isCond3Bullish || + isCond4Bullish || + isCond5Bullish || + isCond6Bullish + // + ; + + // + isBearish = + // + isCond1Bearish || + isCond2Bearish || + isCond3Bearish || + isCond4Bearish || + isCond5Bearish || + isCond6Bearish + // + ; + } + + // + // Summarize Result ... + int requiredPushers = 1; + result = + (isBullish && + longPushers >= requiredPushers) || + (isBearish && + shortPushers >= requiredPushers); + + // + // Preparing Signal Zone ... + if (result) + { + // + iDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Preparing Signal Zone ... + signalZone.to = iTo; + signalZone.dir = iDir; + signalZone.from = iFrom; + signalZone.type = iType; + signalZone.upper = iUpper; + signalZone.lower = iLower; + signalZone.symbol = iSymbol; + signalZone.period = iPeriod; + + // + // Temparory Object ... + color iColor = + isBullish + ? clrAqua + : clrMagenta; + string iName = signalZone.type + "_Conditions_" + ToXString(iDir) + "_" + ToXString(((int)conditions.time)); + + // + CChartObjectVLine *iObj = new CChartObjectVLine(); + has = iObj.Create( + 0, + iName, + 0, + conditions.bars[zIDX].time // + ); + if (has) + { + // + iObj.Color(iColor); + } + + // + // Validate Signal Zone and Draw it ... + has = signalZone.IsValid(); + if (has) + { + // + XCATBPivotStyle iStyle; + iStyle.width = 2; + iStyle.clr = isBullish + ? clrYellow + : clrOrange; + iStyle.style = STYLE_SOLID; + + // + XCBoxObject *iObj; + has = drawer + .drawer + .DrawBox( + signalZone, + iObj // + ); + if (has) + { + drawer.ApplyPivotStyle(iObj, iStyle); + } + } + + // + } + + // + // Validate Result ... + result = + result && + signalZone.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + // + signalZone.Clean(); + conditions.Clean(); + } + + // + return result; +} + +/** + * Check a Signal Zone is Breaked or Not ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param box: XBoxZone instance reference ... + * @param barIndex: int, Bar Index ... + * + * @return ( bool ) + */ +bool IsSignalZoneBreaked( + XCX121XCatbHelper *helper, + XBoxZone &box, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Args ... + result = + box.IsValid() && + helper != NULL; + if (!result) + { + // + // Assume Box Invalid and Breaked + // When Args not Valid ... + result = true; + return result; + } + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // Extract Bars ... + + // + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + + // + result = cBar.Init( + box.symbol, + box.period, + barIndex + 1 // + ); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + // Assume Box Invalid and Breaked + // When Args not Valid ... + result = true; + + // + return result; + } + + // + // Check Box is Breaked or not ... + // a Box Assume Breakes when at least 3 Bars Close over / under applied Price ... + + // + double appliedPrice = + isBullish + ? box.lower + : box.upper; + + // + bool isBullishBreaked = + isBullish && + cBar.close < appliedPrice && + pBar.close < appliedPrice && + p2Bar.close < appliedPrice; + + // + bool isBearishBreaked = + isBearish && + cBar.close > appliedPrice && + pBar.close > appliedPrice && + p2Bar.close > appliedPrice; + + // + result = isBullishBreaked || + isBearishBreaked; + + // + // Cleanup Resources ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040626/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 b/BKPS/14040626/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..9e828f0 --- /dev/null +++ b/BKPS/14040626/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCATBEAPOIExtension Lib +// Description: Library for Adding Extensions on +// XCATBEA POI(s) ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Extensions Library for XCATBEA POI(s)" +#property strict + +// +// Imports ... +#include "../Classes/xcatbea.x-poi.detector.class.mq5" + +// +// Extensions ... + +// +int ExtractPivots( + XBoxZone &extracted[], + ENUM_XCATB_PIVOTS type, + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + Clean(extracted); + + // + bool has = + IsValid(type) && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + ENUM_XCATB_PIVOTS iType = GetPivotType(iBox); + + // + has = iType == type; + if (has) + { + // + AddRef( + iBox, + extracted // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(extracted); + + // + return result; +} diff --git a/BKPS/14040626/XOM1EA/Classes/xom1ea.expert.class.mq5 b/BKPS/14040626/XOM1EA/Classes/xom1ea.expert.class.mq5 new file mode 100644 index 0000000..dcb0828 --- /dev/null +++ b/BKPS/14040626/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -0,0 +1,1094 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXOM1EAExpret ... +// Description: XCXOM1EA Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCXOM1EA Expert Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-alert.class.mq5" +#include "../../Classes/x-saherelm.x-guard.class.mq5" +#include "../../Classes/x-saherelm.x-trade-manager.class.mq5" +#include "../../Classes/x-saherelm.x-volume.class.mq5" +#include "../Classes/xom1ea.signaller.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCXOM1EAExpert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Symbol Configurations ... + string eaSymbolConfiguration; // Symbol Configurations ... + + // + // Management ... + bool eaAllowGuards; // Allow Guards + bool eaAllowTrade; // Allow Trade on Signals + bool eaAllowLongs; // Allow Long Trades + bool eaAllowShorts; // Allow Short Trades + double eaMaxAllowedDrawdownFactor; // Max Allowed DrawDown for Trade + + // + // Volume ... + ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type + double eaStaticVoluem; // Static Volume + double eaDynamicVolumeStepBalance; // Step of Balance for Increase Volume + double eaDynamicVolumeStepVolume; // Step of Volume Increasing + double eaConstantRiskBalance; // Constant Risk Balance per Trade + double eaConstantPercent; // Constant Percent of Balance Per Trade + double eaConstantBalance; // Constant Balance for Calculations + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // Reports ... + bool eaReportNewMonths; // Report New Month + bool eaReportNewWeeks; // Report New Weeks + bool eaReportNewDays; // Report New Days + bool eaReportNewHours; // Report New Hours + bool eaReportTrades; // Report Trades + bool eaReportSignals; // Report Signals + bool eaReportProtector; // Report Protector Actions + bool eaReportRestrictions; // Report Restrictions + bool eaReportAfterTradesBalance; // Report Balance after a Trade Finished + + // + // Collector ... + bool eaSaveTrades; // Save Trades + bool eaSaveSignals; // Save Signals + bool eaSaveWins; // Save Winning Conditions + bool eaSaveLosts; // Save Lost Conditions + bool eaSaveRestrictions; // Save Restriction Reports + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCTrade *eaTrade; // EA Scope Trade Handler ... + XCTradeManager *eaTradeManager; // EA Scope Trade Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + + // + // Tools / Actions / Handlers ... + + // + TOnGuarded onGuardedEventHandler; + TCanAnalyse canAnalyseEventHandler; + TCheckForGuard checkForGuardEventHandler; + + // + // Signal Event Handlers ... + + // + void AddOnSignalEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalEventHandlers // + ); + } + + // + // Trade Event Handlers ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // TODO: Handle this ... + result = true; + + // + return result; + } + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetSaveAlerts(eaSaveAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Volume Manager ... + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Initialize Trader ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + 0, + 0, + eaMaxAllowedDrawdownFactor // + ); + + // + // Trade Handler Attachments ... + + // + // Position Modifiy Event Handlers ... + count = ArraySize(mOnModifyEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); + } + } + + // + // Position Stop Loss Event Handlers ... + count = ArraySize(mStopLossEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); + } + } + + // + // Position Take Profit Event Handlers ... + count = ArraySize(mTakeProfitEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); + } + } + + // + // Position Force Close Event Handlers ... + count = ArraySize(mOnForceCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); + } + } + + // + // Deals Changed Event Handlers ... + count = ArraySize(mDealsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); + } + } + + // + // Orders Changed Event Handlers ... + count = ArraySize(mOrdersChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); + } + } + + // + // Positions Changed Event Handlers ... + count = ArraySize(mPositionsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); + } + } + + // + // Trade Changed Event Handlers ... + count = ArraySize(mTradeStateChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); + } + } + + // + // Postion Partially Close Event Handlers ... + count = ArraySize(mOnPartialCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); + } + } + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrade // + ); + + // + // Attach Event Handler ... + eaGuard.onGuardEventListener = onGuardedEventHandler; + + // + // Initialize Trae Manager ... + eaTradeManager = new XCTradeManager( + eaAlert, + eaTrade, + eaVolume, + eaGuard // + ); + + // + // Configuring Trade Manager ... + + // + // Attache Check For Guard Event Listener ... + eaTradeManager.checkForGuardEventListener = checkForGuardEventHandler; + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Symbol Configuration ... + XSymbolTradeConfig symbolConfigurations[]; + eaTradeManager.SetSymbolConfigurations(eaSymbolConfiguration); + count = eaTradeManager.FillSymbolConfigurations(symbolConfigurations); + has = IsValidSize(count); + if (has) + { + // + // XFIMA ... + + // + XOM1Inputs iFIMAOMInputs; + iFIMAOMInputs.Default(); + iFIMAOMInputs.showFiboZone = true; + + // + XOM1SignallerConfig iFIMASignallerConfig; + iFIMASignallerConfig.processAllTicks = false; + + // + XCXOM1SignallerBase *iFIMASignaller = NULL; + + // + // iMAC5020 ... + + // + XOM1Inputs iMAC5020OMINputs; + iMAC5020OMINputs.Default(); + iMAC5020OMINputs.showPV = false; + iMAC5020OMINputs.showSAR = false; + iMAC5020OMINputs.maFastLength = 20; + iMAC5020OMINputs.maSlowLength = 50; + iMAC5020OMINputs.showFiboZone = false; + + // + XOM1SignallerConfig iMAC5020SignallerConfig; + iMAC5020SignallerConfig.processAllTicks = false; + + // + XCXIMAC5020Signaller *iMAC5020Signaller = NULL; + + // + // Configure Signallers ... + for (int i = 0; i < count; i++) + { + // + // Register XFIMA Signaller ... + // iFIMASignaller = new XCXOM1FIMASignaller( + // "XDZN", + // symbolConfigurations[i].symbol, + // symbolConfigurations[i].period, + // iFIMAOMInputs, + // iFIMASignallerConfig // + // ); + // if (iFIMASignaller != NULL) + // { + // // + // // Register Signaller ... + // XCXOM1SignallerBase *signaller = iFIMASignaller; + // RegisterSignaller(signaller); + // ZeroMemory(signaller); + // } + + // + // Register XIMAC5020 Signaller ... + iMAC5020Signaller = new XCXIMAC5020Signaller( + "XIMAC5020", + symbolConfigurations[i].symbol, + symbolConfigurations[i].period, + iMAC5020OMINputs, + iMAC5020SignallerConfig // + ); + if (iMAC5020Signaller != NULL) + { + // + // Register Signaller ... + XCXOM1SignallerBase *signaller = iMAC5020Signaller; + RegisterSignaller(signaller); + ZeroMemory(signaller); + } + } + + // + // Cleanup Resources ... + + // + iFIMAOMInputs.Clean(); + iMAC5020OMINputs.Clean(); + ZeroMemory(iFIMASignaller); + iFIMASignallerConfig.Clean(); + ZeroMemory(iMAC5020Signaller); + iMAC5020SignallerConfig.Clean(); + } + SpecifiedClean(symbolConfigurations); + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + eaTimeTracker.Clean(); + + // + SpecifiedClean(eaSignallers); + SpecifiedClean(mOnSignalEventHandlers); + SpecifiedClean(mOnModifyEventHandlers); + SpecifiedClean(mStopLossEventHandlers); + SpecifiedClean(mTakeProfitEventHandlers); + SpecifiedClean(mOnForceCloseEventHandlers); + SpecifiedClean(mDealsChangedEventHandlers); + SpecifiedClean(mOrdersChangedEventHandlers); + SpecifiedClean(mOnPartialCloseEventHandlers); + SpecifiedClean(mPositionsChangedEventHandlers); + SpecifiedClean(mTradeStateChangedEventHandlers); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + // + // Time Report ... + HandleTimeReport(); + + // + // Manage Trades ... + eaTradeManager.Manage(); + + // + int count = ArraySize(eaSignallers); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + // Loop through Signallers ... + for (int i = 0; i < count; i++) + { + // + // Calling Process Ticks on Signaller ... + eaSignallers[i].ProcessTick(0); + } + + // + // Guard Implememnting ... + // TODO: Implement this ... + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + eaTrade.HandleOnTrade(); + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Signal Event Handler ... + void HandleOnSignalTriggered(XSignal &signal) + { + eaTradeManager.HandleSignal(signal); + } + + /** + * Check For Guard Event Handler ... + * + * @param guards: XGuard[] + * + * @return ( int ) + */ + int CheckForGuardTriggered(XGuard &guards[]) + { + // + int result = 0; + + // + if (!HasChild(eaSignallers)) + { + return result; + } + + // + int count = ArraySize(eaSignallers); + for (int i = 0; i < count; i++) + { + // + XGuard iGuards[]; + int iGuardsCount = eaSignallers[i].CheckForGuard(iGuards); + if (IsValidSize(iGuardsCount)) + { + // + Copy( + iGuards, + guards, + false // + ); + } + + // + SpecifiedClean(iGuards); + } + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Handle Guard Events ... + * + * @param action: ENUM_X_GUARD_ACTIONS + * @param positions: XPosition[] + */ + void OnGuardedTriggered( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // + ) + { + eaTradeManager.HandleGuardEvent(action, positions); + } + + // + // Check Can Analyse ... + bool HandleCanAnalyseEventTriggered( + string symbol, + ENUM_TIMEFRAMES period, + datetime time // + ) + { + return eaTradeManager.CanAnalyse( + symbol, + period, + time // + ); + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + eaTradeManager.HandleSL(deal); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + eaTradeManager.HandleTP(deal); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + eaTradeManager.HandleForceClose(position); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + eaTradeManager.HandlePartiallyClosed( + ticket, + profit, + comment // + ); + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // Protected ... + protected: + // + + /** + * Report Time Changes based on Given Configurations ... + */ + void HandleTimeReport() + { + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } + } + + /** + * Register Signaller ... + */ + void RegisterSignaller(XCXOM1SignallerBase *signaller) + { + // + // Validate Signaller ... + if (signaller == NULL) + { + return; + } + + // + // Attach Signaller OnSignal Event Handlers if Exists ... + int count = ArraySize(mOnSignalEventHandlers); + bool has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + signaller.AddOnSignalEventHandler(mOnSignalEventHandlers[i]); + } + } + + // + // Attach Can Analyse Event Handler ... + signaller.canAnalyseEventListener = canAnalyseEventHandler; + + // + // Register Signaller ... + Add( + signaller, + eaSignallers // + ); + } + + // + // Private ... + private: + // + // Props ... + + // + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + TOnSignal mOnSignalEventHandlers[]; // Signal Recieved Event Handlers ... + + // + XCXOM1SignallerBase *eaSignallers[]; // All Registered Signallers ... +}; + +// diff --git a/BKPS/14040626/XOM1EA/Classes/xom1ea.signaller.class.mq5 b/BKPS/14040626/XOM1EA/Classes/xom1ea.signaller.class.mq5 new file mode 100644 index 0000000..0fc24ab --- /dev/null +++ b/BKPS/14040626/XOM1EA/Classes/xom1ea.signaller.class.mq5 @@ -0,0 +1,877 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXOM1Signaller ... +// Description: XOM1EA Signaller Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XOM1EA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.xom1.helper.mq5" +#include "../Classes/xom1ea.x-poi.drawer.class.mq5" +#include "../Libraries/xom1ea.lib.mq5" + +// +// Definitions ... + +// +// All Available Signaller Configurations +// which allow to Decide Based on Zones ... +struct XOM1SignallerConfig +{ + // + // Props ... + bool processAllTicks; // Do Process All Ticks ... + + // + // Constructor ... + XOM1SignallerConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + ZeroMemory(this); + } +}; + +// +// Implementation ... + +// +// Base Signaller Class ... +// Provides Zone Detection Mechanism ... +class XCXOM1SignallerBase +{ + // + // Public ... + public: + // + // Props ... + string name; // Name ... + string symbol; // Symbol ... + XOM1Zone zones[]; // Detected Zones ... + XOM1Inputs inputs; // Indicator Inputs ... + ENUM_TIMEFRAMES period; // Period ... + XCXOM1POIDrawer drawer; // POI Drawer ... + XOM1SignallerConfig config; // Configuration ... + TCanAnalyse canAnalyseEventListener; // CanAnalyse Event Listener ... + + // + // Constructor ... + XCXOM1SignallerBase( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XOM1Inputs &_inputs, // Indicator Inputs ... + XOM1SignallerConfig &_config // Config ... + ) + { + // + // Validate ... + bool isValid = + IsSpecifiedValid(_name) && + IsSpecifiedValid(_symbol) && + IsSpecifiedValid(_period) && + _inputs.IsValid(); + if (!isValid) + { + return; + } + + // + // Make Helper Class Instance ... + mHelper = new XCXOM1Helper(); + bool isInited = mHelper.Init( + _symbol, + _period, + _inputs // + ); + if (!isInited) + { + // + delete mHelper; + ZeroMemory(mHelper); + return; + } + + // + // Set Props ... + name = _name; + symbol = _symbol; + period = _period; + inputs = _inputs; + config = _config; + + // + // Set Dfault Values ... + mProcessedTicksCount = 0; + mLastCheckedBarTime = NULL; + } + + // + // Deconstructor ... + ~XCXOM1SignallerBase() + { + // + inputs.Clean(); + + // + SpecifiedClean(zones); + + // + delete mHelper; + ZeroMemory(mHelper); + } + + // + // Signal Event Handlers ... + + // + void AddOnSignalEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalEventHandlers // + ); + } + + // + void NotifyOnSignalEvent(XSignal &signal) + { + // + int count = ArraySize(mOnSignalEventHandlers); + bool has = IsValidSize(count) && signal.IsValid(); + if (!has) + { + return; + } + + // + // Calling Event Handlers ... + for (int i = 0; i < count; i++) + { + mOnSignalEventHandlers[i](signal); + } + } + + // + // Actions ... + + /** + * Handle Ticks Process ... + * + * @param barIndex: int + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Virtuals ... + + // + // Protected ... + protected: + // + // Props ... + + // + XCXOM1Helper *mHelper; // Indicator Helper ... + + // + int mProcessedTicksCount; // Prcoessed Ticks Count ... + datetime mLastCheckedBarTime; // Last Checked Bar Time ... + + /** + * Check Permissions for Analysing Market ... + * + * @param _symbol: Symbol ... + * @param _period: Period ... + * @param time: Specified Date Time ... + * + * @return ( bool ) + */ + bool CanAnalyse( + string _symbol, + ENUM_TIMEFRAMES _period, + datetime time // + ) + { + // + bool result = false; + + // + if (canAnalyseEventListener != NULL) + { + // + result = canAnalyseEventListener( + _symbol, + _period, + time // + ); + } + else + { + result = true; + } + + // + return result; + } + + /** + * Handle New Bar's Process ... + * + * @param barIndex: int + */ + void ProcessNewBar(int barIndex = 0) + { + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Try to Update Zone's Lifetime ... + int count = ArraySize(zones); + bool has = count > 0; + if (has) + { + // + // Loop through Zones ... + for (int i = 0; i < count; i++) + { + // + // Update Lifetime by Bar Index ... + // zones[i].UpdateByBarIndex(barIndex); + + // + // drawer.DrawZone( + // zones[i], + // true, // Draw Price ... + // true, // Draw Middle ... + // true // Draw From ... + // ); + } + } + + // + // Check XOMZones Validations ... + } + + /** + * Process Exists Zones ... + * Detect a Zone for trigger ... + * + * @param barIndex: int + */ + void ProcessZones(int barIndex = 0) + { + // + // Check Zones Exists ... + int count = ArraySize(zones); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + // Loop Through Zones ... + for (int i = 0; i < count; i++) + { + // + } + } + + /** + * Converts iZone to Signal and Notify Signal ... + * + * @param iZone: XOM1Zone + */ + void PrepareSignal(XOM1Zone &zone) + { + // + // Validate Zone ... + if (!zone.IsValid()) + { + return; + } + + // + // Create Signal ... + XSignal signal; + + // + signal.time = zone.to; + signal.provider = name; + signal.symbol = zone.symbol; + signal.period = zone.period; + signal.mode = X_ORDER_MODE_MARKET; + signal.conditions = "XConditions"; + signal.comment = ToXString(zone.reason); + signal.type = zone.IsBullish() + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + // Get Entry ... + signal.entry = GetXEntry(zone.symbol, zone.dir); + + // + // Calculate SL ... + double providedSL = zone.IsBullish() + ? zone.lower + : zone.upper; + signal.sl = providedSL; + + // + // Calculate Risk ... + double risk = MathAbs(signal.entry - signal.sl); + + // + // Calculate Reward ... + double r2r = 2; + double reward = risk * r2r; + + // + // Calculate TP ... + double providedTP = zone.IsBullish() + ? signal.entry + reward + : signal.entry - reward; + signal.tp = providedTP; + + // + // Calculate Targets ... + // TODO: Handle this ... + + // + // Set Min Volume ... + signal.volume = 0.01; + + // + NotifyOnSignalEvent(signal); + } + + // + // Private ... + private: + // + // Props ... + + // + TOnSignal mOnSignalEventHandlers[]; // Signal Recieved Event Handlers ... +}; + +// +class XCXOM1FIMASignaller : public XCXOM1SignallerBase +{ + // + // Public ... + public: + // + + // + // Constructor ... + XCXOM1FIMASignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XOM1Inputs &_inputs, // Indicator Inputs ... + XOM1SignallerConfig &_config // Config ... + ) : XCXOM1SignallerBase(_name, + _symbol, + _period, + _inputs, + _config // + ) + { + } + + // + // Deconstructor ... + ~XCXOM1FIMASignaller() + { + } + + // + // Overrides ... + + /** + * Handle Ticks Process ... + * + * @param barIndex: int + */ + virtual void ProcessTick(int barIndex = 0) + { + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Define Requirements ... + XOHCL iBar; + bool has = false; + bool isNewBar = false; + + // + // Get Current Bar Time ... + datetime cBarTime = GetBarTime( + symbol, + period, + barIndex // + ); + + // + // Validate Bar Time ... + has = IsSpecifiedValid(cBarTime); + if (!has) + { + return; + } + + // + // Check Process Permissions ... + has = CanAnalyse(symbol, period, cBarTime); + if (!has) + { + return; + } + + // + // Check if new Bar, Reset Processed Ticks Count ... + isNewBar = cBarTime > mLastCheckedBarTime; + if (isNewBar) + { + // + mProcessedTicksCount = 0; + ProcessNewBar(barIndex); + } + + // + // Check Allow Process ... + // Process All Ticks ... + // Process New Bars ... + has = config.processAllTicks || + (!config.processAllTicks && isNewBar); + if (!has) + { + return; + } + + // + // Set Last Works ... + mProcessedTicksCount++; + mLastCheckedBarTime = cBarTime; + + // + // Initialize iBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Update Indicator Helper ... + mHelper.Update(barIndex); + + // + // Process Exists Zone ... + ProcessZones(barIndex); + + // + // Do All Processing Mechanism ... + + // + // Reading Conditions from Helper ... + XOM1Conditions iConditions; + has = mHelper.GetConditions( + iConditions, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + iConditions.Clean(); + return; + } + + // + int zIdx = 0; + int cIdx = zIdx + 1; + int pIdx = cIdx + 1; + int p2Idx = pIdx + 1; + + // + // Check Zones Flags ... + bool checkPVZones = false; + bool checkMAZones = true; + + // + // Check PV Zones ... + if (checkPVZones) + { + // + // Check New Peak or Vale Happens ... + + // + // New Vale Over Last ... + bool isValeReason = iConditions.valeBuffer[cIdx] > iConditions.valeBuffer[pIdx]; + + // + // New Peak Under Last ... + bool isPeakReason = iConditions.peakBuffer[cIdx] < iConditions.peakBuffer[pIdx]; + + // + has = isValeReason || isPeakReason; + if (has) + { + // + // Prepare Reason ... + ENUM_XOM1_ZONE_REASON iReason = isValeReason + ? X_OM1_ZONE_REASON_VALE + : X_OM1_ZONE_REASON_PEAK; + + // + // Extract Upper / Lower Values ... + double iUpper = iConditions.peakBuffer[pIdx]; + double iLower = iConditions.valeBuffer[pIdx]; + + // + // Calculate Mid Range ... + double iMiddle = iLower + ((iUpper - iLower) / 2); + if (iMiddle > 0) + { + iMiddle = NormalizePrice(iMiddle, symbol); + } + + // + // Detect Reason Price ... + double iPrice = + isValeReason + ? iConditions.valeBuffer[cIdx] + : iConditions.peakBuffer[cIdx]; + if (iPrice > 0) + { + iPrice = NormalizePrice(iPrice, symbol); + } + + // + // Detect Reason Direction ... + ENUM_X_DIRECTION iDir = iPrice > iMiddle + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Try to Initialize Zone ... + XOM1Zone iZone; + has = iZone.Init( + symbol, + period, + name, // Signaller Name ... + iUpper, + iLower, + iPrice, + iDir, + iReason, + iConditions.bars[pIdx].time, // From ... + iConditions.bars[zIdx].time // To + ); + if (has) + { + // + // Add New Detected Zone to Zones ... + AddRef( + iZone, + zones // + ); + + // + // Prepare Signal ... + PrepareSignal(iZone); + } + + // + iZone.Clean(); + } + } + + // + // Check MA Zones ... + if (checkMAZones) + { + // + // Crossed Over ... + bool isFastCrossedOverSlow = iConditions.maFastBuffer[cIdx] > iConditions.maSlowBuffer[cIdx] && + !(iConditions.maFastBuffer[pIdx] >= iConditions.maSlowBuffer[pIdx]); + + // + // Crossed Under ... + bool isFastCrossedUnderSlow = iConditions.maFastBuffer[cIdx] < iConditions.maSlowBuffer[cIdx] && + !(iConditions.maFastBuffer[pIdx] <= iConditions.maSlowBuffer[pIdx]); + + // + double iFast = iConditions.maFastBuffer[cIdx]; + double iSlow = iConditions.maSlowBuffer[cIdx]; + double iFibUpper = iConditions.fiboUpperBuffer[cIdx]; + double iFibLower = iConditions.fiboLowerBuffer[cIdx]; + + // + double iValues[] = { + iFast, + iSlow, + iFibUpper, + iFibLower // + }; + + // + // Extract Upper / Lower Values ... + double iUpper = GetMax(iValues); + double iLower = GetMin(iValues); + + // + double iZoneUpper = MathMax(iFibUpper, iFibLower); + double iZoneLower = MathMin(iFibUpper, iFibLower); + + // + has = isFastCrossedOverSlow || isFastCrossedUnderSlow; + + // + // Validate Cross Between Zone ... + if (has) + { + // + // Validate MA Place ... + has = iFast >= iZoneLower && + iFast <= iZoneUpper && + iSlow >= iZoneLower && + iSlow <= iZoneUpper; + + // + // Validate PSar ... + bool isSarBullish = iConditions.sarStateBuffer[cIdx] > 0; + bool isSarBearish = iConditions.sarStateBuffer[cIdx] < 0; + has = + has && + (isFastCrossedOverSlow + ? isSarBullish + : isSarBearish // + ); + + // + // Validate Fibo Zone ... + for (int idx = cIdx; idx < cIdx + 2; idx++) + { + // + // Check Fibo Upper ... + has = has && + iConditions.fiboUpperBuffer[idx] == iConditions.fiboUpperBuffer[idx + 1]; + if (!has) + { + break; + } + + // + // Check Fibo Lower ... + has = has && + iConditions.fiboLowerBuffer[idx] == iConditions.fiboLowerBuffer[idx + 1]; + if (!has) + { + break; + } + } + } + + // + // Moving Forward if Validated ... + if (has) + { + // + // Prepare Reason ... + ENUM_XOM1_ZONE_REASON iReason = isFastCrossedOverSlow + ? X_OM1_ZONE_REASON_FCOS + : X_OM1_ZONE_REASON_FCUS; + + // + // Calculate Mid Range ... + double iMiddle = iLower + ((iUpper - iLower) / 2); + if (iMiddle > 0) + { + iMiddle = NormalizePrice(iMiddle, symbol); + } + + // + // Detect Reason Price ... + double iPrice = iConditions.maFastBuffer[cIdx]; + if (iPrice > 0) + { + iPrice = NormalizePrice(iPrice, symbol); + } + + // + // Detect Reason Direction ... + ENUM_X_DIRECTION iDir = isFastCrossedOverSlow + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Try to Initialize Zone ... + XOM1Zone iZone; + has = iZone.Init( + symbol, + period, + name, // Signaller Name ... + iZoneUpper, + iZoneLower, + iPrice, + iDir, + iReason, + iConditions.bars[pIdx].time, // From ... + iConditions.bars[zIdx].time // To + ); + if (has) + { + // + // Add New Detected Zone to Zones ... + AddRef( + iZone, + zones // + ); + + // + // Prepare Signal ... + PrepareSignal(iZone); + } + + // + iZone.Clean(); + } + + // + Clean(iValues); + } + + // + // Clean Resources ... + iBar.Clean(); + iConditions.Clean(); + } +}; + +// +class XCXIMAC5020Signaller : public XCXOM1SignallerBase +{ + // + // Public ... + public: + // + + // + // Constructor ... + XCXIMAC5020Signaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XOM1Inputs &_inputs, // Indicator Inputs ... + XOM1SignallerConfig &_config // Config ... + ) : XCXOM1SignallerBase(_name, + _symbol, + _period, + _inputs, + _config // + ) + { + } + + // + // Deconstructor ... + ~XCXIMAC5020Signaller() + { + } + + // + // Overrides ... + + /** + * Handle Ticks Process ... + * + * @param barIndex: int + */ + virtual void ProcessTick(int barIndex = 0) + { + } +}; + +// +// Extensions ... + +// \ No newline at end of file diff --git a/BKPS/14040626/XOM1EA/Classes/xom1ea.x-poi.drawer.class.mq5 b/BKPS/14040626/XOM1EA/Classes/xom1ea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..9f37841 --- /dev/null +++ b/BKPS/14040626/XOM1EA/Classes/xom1ea.x-poi.drawer.class.mq5 @@ -0,0 +1,219 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXOM1POIDrawer ... +// Description: XOM1EA POI Drawer Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XOM1EA POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/xom1ea.lib.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCXOM1POIDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXOM1POIDrawer() + { + } + + // + // Deconstructor ... + ~XCXOM1POIDrawer() + { + mObjects.Clear(); + } + + // + // Actions ... + + /** + * Draw Specified Zone ... + * + * @param zone: XOM1Zone + * @param drawPrice: bool + * @param drawMiddle: bool + */ + void DrawZone( + XOM1Zone &zone, + bool drawPrice = false, + bool drawMiddle = false, + bool drawFrom = false // + ) + { + // + bool has = false; + + // + // Validate ... + has = zone.IsValid(); + if (!has) + { + return; + } + + // + // Converts to Box ... + XBoxZone box; + has = zone.ToBox(box); + if (!has) + { + // + box.Clean(); + return; + } + + // + // Draw Box ... + XCBoxObject *object; + has = mDrawer.DrawBox( + box, + object, + true // Ignore At ... + ); + if (has) + { + mObjects.Add(object); + } + + // + // Draw Price ... + if (drawPrice) + { + // + CChartObjectTrend *mLineObj; + string mLineName = "pl_" + ToMD5(zone.GetTag()); + mLineObj = new CChartObjectTrend(); + has = mLineObj.Create( + mDrawer.ChartIdentification(), + mLineName, + mDrawer.SubWindowIdentification(), + zone.from, + zone.price, + zone.to, + zone.price // + ); + if (has) + { + // + mDrawer.ApplyStyle( + mLineObj, + zone.dir // + ); + + // + mObjects.Add(mLineObj); + } + } + + // + // Draw Middle ... + if (drawMiddle) + { + // + CChartObjectTrend *mLineObj; + double mlPrice = zone.lower + ((zone.upper - zone.lower) / 2); + string mLineName = "ml_" + ToMD5(zone.GetTag()); + mLineObj = new CChartObjectTrend(); + has = mLineObj.Create( + mDrawer.ChartIdentification(), + mLineName, + mDrawer.SubWindowIdentification(), + zone.from, + mlPrice, + zone.to, + mlPrice // + ); + if (has) + { + // + mDrawer.ApplyStyle( + mLineObj, + zone.dir // + ); + + // + mObjects.Add(mLineObj); + } + } + + // + // Draw From ... + if (drawFrom) + { + // + CChartObjectVLine *mLineObj; + string mLineName = "mfl_" + ToMD5(zone.GetTag()); + mLineObj = new CChartObjectVLine(); + has = mLineObj.Create( + mDrawer.ChartIdentification(), + mLineName, + mDrawer.SubWindowIdentification(), + zone.from // + ); + if (has) + { + // + mDrawer.ApplyStyle( + mLineObj, + zone.dir // + ); + + // + mObjects.Add(mLineObj); + } + } + + // + // Clean Resources ... + box.Clean(); + } + + /** + * Clear Drawn Objects ... + */ + void Clear() + { + mObjects.Clear(); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + CArrayObj mObjects; // Drawn Objects ... + XCPOIDrawer mDrawer; // Base POI Drawer ... +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/XOM1EA/Libraries/xom1ea.lib.mq5 b/BKPS/14040626/XOM1EA/Libraries/xom1ea.lib.mq5 new file mode 100644 index 0000000..9652bb0 --- /dev/null +++ b/BKPS/14040626/XOM1EA/Libraries/xom1ea.lib.mq5 @@ -0,0 +1,429 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XOM1EA Lib +// Description: Library for XOM1EA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Library for XOM1EA Signaller" +#property strict + +// +// Imports ... +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Zone Creation Reason ... +enum ENUM_XOM1_ZONE_REASON +{ + X_OM1_ZONE_REASON_NONE, // NONE + X_OM1_ZONE_REASON_PEAK, // PEAK + X_OM1_ZONE_REASON_VALE, // VALE + X_OM1_ZONE_REASON_FCOS, // FCOS + X_OM1_ZONE_REASON_FCUS, // FCUS +}; + +/** + * Validate a Zone Creation Reason ... + * + * @param value: ENUM_XOM1_ZONE_REASON + * + * @return ( bool ) + */ +bool IsXValid(ENUM_XOM1_ZONE_REASON value) +{ + // + bool result = false; + + // + result = value != X_OM1_ZONE_REASON_NONE; + + // + return result; +} + +/** + * Converts a Zone Reason to String ... + * + * @param value: ENUM_XOM1_ZONE_REASON + * + * @return ( string ) + */ +string ToXString(ENUM_XOM1_ZONE_REASON value) +{ + return EnumToString(value); +} + +/** + * Converts a Zone Reason to String ... + * + * @param value: ENUM_XOM1_ZONE_REASON + * + * @return ( string ) + */ +ENUM_XOM1_ZONE_REASON FromXString(string value) +{ + // + ENUM_XOM1_ZONE_REASON result = X_OM1_ZONE_REASON_NONE; + + // + if (!IsSpecifiedValid(value)) + { + return result; + } + + // + if (value == ToXString(X_OM1_ZONE_REASON_NONE)) + { + result = X_OM1_ZONE_REASON_NONE; + } + else if (value == ToXString(X_OM1_ZONE_REASON_PEAK)) + { + result = X_OM1_ZONE_REASON_PEAK; + } + else if (value == ToXString(X_OM1_ZONE_REASON_VALE)) + { + result = X_OM1_ZONE_REASON_VALE; + } + else if (value == ToXString(X_OM1_ZONE_REASON_FCOS)) + { + result = X_OM1_ZONE_REASON_FCOS; + } + else if (value == ToXString(X_OM1_ZONE_REASON_FCUS)) + { + result = X_OM1_ZONE_REASON_FCUS; + } + + // + return result; +} + +// +// this is a Zone Which +// we start Looking for +// Signal Detecting ... +struct XOM1Zone +{ + // + // Props ... + + // + string symbol; // Symbol + ENUM_TIMEFRAMES period; // Period + string signaller; // Signaller Identifier + datetime from; // Detection Time + datetime to; // Lifetime + ENUM_X_DIRECTION dir; // Direction + ENUM_XOM1_ZONE_REASON reason; // Creation Reason + double upper; // Upper Level + double lower; // Lower Level + double price; // Reason Price + + // + // Constructor ... + XOM1Zone() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _symbol: Symbol + * @param _period: Period + * @param _signaller: Signaller Identifier + * @param _upper: Upper Value (PEAK) + * @param _lower: Lower Value (VALE) + * @param _price: Price (Changed Peak or Vale) + * @param _dir: Direction + * @param _reason: Creation Reason + * @param _from: Detection Time + * @param _to: Lifetime Time + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + string _signaller, + double _upper, + double _lower, + double _price, + ENUM_X_DIRECTION _dir, + ENUM_XOM1_ZONE_REASON _reason, + datetime _from, + datetime _to = NULL // + ) + { + // + to = _from; + dir = _dir; + from = _from; + upper = _upper; + lower = _lower; + price = _price; + symbol = _symbol; + period = _period; + reason = _reason; + signaller = _signaller; + + // + if (IsSpecifiedValid(_to)) + { + to = _to; + } + + // + bool result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + /** + * Update Lifetime by Data ... + * + * @param _to: datetime + */ + void UpdateByDate(datetime _to) + { + // + // Validate ... + bool isValid = IsValid() && + IsSpecifiedValid(_to) && + _to > to; + if (!isValid) + { + return; + } + + // + to = _to; + } + + /** + * Update Lifetime by BarIndex ... + * + * @param barIndex: int + */ + void UpdateByBarIndex(int barIndex) + { + // + // Normalize ... + if (barIndex <= 0) + { + barIndex = 0; + } + + // + if (!IsValid()) + { + return; + } + + // + datetime _to = GetBarTime( + symbol, + period, + barIndex // + ); + if (!IsSpecifiedValid(_to)) + { + return; + } + + // + UpdateByDate(_to); + } + + /** + * Clean ... + */ + void Clean() + { + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(signaller) && + IsSpecifiedValid(from) && + IsSpecifiedValid(to) && + to >= from && + HasDirection(dir) && + IsXValid(reason) && + upper > 0 && + lower > 0 && + price > 0 && + upper > lower && + price <= upper && + price >= lower + // + ; + + // + return result; + } + + /** + * Calculate Lifetime Age ... + * + * @return ( int ) + */ + int GetBarLife() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int fromIDX = GetBarIndex( + symbol, + period, + from // + ); + int toIDX = GetBarIndex( + symbol, + period, + to // + ); + bool isValid = IsValidIndex(fromIDX) && IsValidIndex(toIDX); + if (!isValid) + { + return result; + } + + // + result = MathAbs(fromIDX - toIDX); + + // + return result; + } + + /** + * Check Zone is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + return IsValid() && IsSpecifiedBullish(dir); + } + + /** + * Check Zone is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + return IsValid() && IsSpecifiedBearish(dir); + } + + /** + * Converts to Box ... + * + * @param box: Dest + * + * @return ( bool ) + */ + bool ToBox(XBoxZone &box) + { + // + bool result = false; + + // + box.Clean(); + result = IsValid(); + if (!result) + { + return result; + } + + // + box.to = to; + box.dir = dir; + box.from = from; + box.upper = upper; + box.lower = lower; + box.symbol = symbol; + box.period = period; + box.type = signaller; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + /** + * Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + result = "XOM1Zone_" + + symbol + "_" + + ToXString(period) + "_" + + signaller + "_" + + ToXString(dir) + "_" + + ToXString(reason) + "_" + + ToXString(TimeToSeconds(from)); + + // + return result; + } +}; + +// \ No newline at end of file diff --git a/BKPS/14040626/compile.cmd b/BKPS/14040626/compile.cmd new file mode 100644 index 0000000..d70eb77 --- /dev/null +++ b/BKPS/14040626/compile.cmd @@ -0,0 +1,26 @@ +@echo off + + set METAEDITOR="C:\Program Files\MetaTrader 5 General\MetaEditor64.exe" + set "LOGFILE=%~dpn1.log" + + if "%~1"=="" ( + echo "You must specify the first parameter to this batch file." + goto end + ) + + :: Compile the MQL5 way + %METAEDITOR% /compile:%1 /log + :: 0 = failed + :: 1 = everything good + echo "Error level %ERRORLEVEL%" + + :: This dumps the log file to stdout so it can be seen. + :: It's assumed to be in the same directory as the expert file. + type "%LOGFILE%" + + :: Once shown, get rid of the .log file. + erase "%LOGFILE%" + +:end + :: If I want the CMD.exe window to go away, use exit + ::exit %ERRORLEVEL% \ No newline at end of file diff --git a/BKPS/14040626/mqlHelper.js b/BKPS/14040626/mqlHelper.js new file mode 100644 index 0000000..8fe4e41 --- /dev/null +++ b/BKPS/14040626/mqlHelper.js @@ -0,0 +1,19 @@ +/** + * XMQL Helper CLI Tools ... + * a module for handle MQL5 Commands running ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// Read Command Arguments ... +let cmdName = process.argv[2]; + +// +XProjectTools.runCommand(cmdName); diff --git a/BKPS/14040626/package.json b/BKPS/14040626/package.json new file mode 100644 index 0000000..f3ebc38 --- /dev/null +++ b/BKPS/14040626/package.json @@ -0,0 +1,31 @@ +{ + "name": "mql5", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "true": "", + "aaa": "|----------|", + "aab": "| Commons |", + "aac": "|----------|", + "mqlHelper": "node mqlHelper.js", + "cleanupEx": "npm run mqlHelper cleanup", + "compileWorkspace": "npm run mqlHelper *", + "compileExperts": "npm run mqlHelper experts", + "compileLibraries": "npm run mqlHelper libraries", + "compileHelpers": "npm run mqlHelper helpers", + "compileClasses": "npm run mqlHelper classes", + "compileIndicators": "npm run mqlHelper indicators", + "repackXCATBEA": "node prepareXCATBEA.js", + "repackXOM1EA": "node prepareXOM1EA.js" + }, + "repository": { + "type": "git", + "url": "https://git.saherelmhub.ir/saherelm/MQL5TestWorkspace.git" + }, + "author": "Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)", + "license": "ISC", + "devDependencies": { + "shx": "^0.3.4" + } +} diff --git a/BKPS/14040626/prepareXCATBEA.js b/BKPS/14040626/prepareXCATBEA.js new file mode 100644 index 0000000..797e213 --- /dev/null +++ b/BKPS/14040626/prepareXCATBEA.js @@ -0,0 +1,35 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XCATBEA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "XCATBEA/*", // XCATBEA Projects ... + "Indicators/x-saherelm.x121.xcatb", // Required Indicators + "Helpers/x-saherelm.x121.xcatb.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.x121.xcatb.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject( + projectName, + projectResources + ); +} + + + diff --git a/BKPS/14040626/prepareXOM1EA.js b/BKPS/14040626/prepareXOM1EA.js new file mode 100644 index 0000000..82f073d --- /dev/null +++ b/BKPS/14040626/prepareXOM1EA.js @@ -0,0 +1,29 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XOM1EA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "XOM1EA/*", // XOM1EA Projects ... + "Indicators/x-saherelm.xom1", // Required Indicators + "Helpers/x-saherelm.xom1.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.xom1.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject(projectName, projectResources); +} diff --git a/BKPS/14040626/x-mql-project.tools.js b/BKPS/14040626/x-mql-project.tools.js new file mode 100644 index 0000000..69536d0 --- /dev/null +++ b/BKPS/14040626/x-mql-project.tools.js @@ -0,0 +1,495 @@ +/** + * XProject Tools Module ... + * a module for handle MQL5 Projects Compile and Packing ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const execSync = require("child_process").execSync; +const XFileTools = require("./Documents/JsModules/x-file.tools"); +const XShellTools = require("./Documents/JsModules/x-shell.tools"); +const XColorTools = require("./Documents/JsModules/x-color.tools"); +const XTypeTools = require("./Documents/JsModules/x-type-detector.tools"); + +// +// Definitions ... +const packsPath = XFileTools.joinPath(".", "Packs"); +const workspacePaths = [ + "Classes", // Required Classes + "Experts", // Expert Advisers + "Helpers", // Indicator's Helpers Classes + "Indicators", // Required Indicators + "Libraries", // Required Libraries + "XCATBEA", // XCATBEA Projects ... + "XOM1EA", // XOM1EA Projects ... +]; + +// +//#region Tools ... + +/** + * Handle Compile and Pack Projects ... + * + * @param {string} projectName + * @param {string[]} resources + * @param {boolean} forceCleanup + * @param {boolean} forceCompileIndicators + */ +async function prepareProject( + projectName = "", + resources = [], + forceCleanup = true, + forceCompileIndicators = true +) { + // + // Check Resources Has Child ... + let isValidArgs = + resources.length > 0 && + XTypeTools.isArray(resources); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Resource List ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Check Project Name is Valid ... + isValidArgs = + projectName.length > 0 && + XTypeTools.isString(projectName); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Empty Project Name ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Prepare Pack Folder Exists ... + let isExists = XFileTools.isDirectoryExists(packsPath); + if (!isExists) { + XFileTools.createDirectory(packsPath); + } + + // + // Check Folder Exists or not ... + // if Exists Remove it ... + // Create Project Folder on Packs ... + const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName); + isExists = XFileTools.isDirectoryExists(prjFolderOnPacks); + if (isExists) { + await XFileTools.removeDirectory(prjFolderOnPacks, true); + } + XFileTools.createDirectory(prjFolderOnPacks); + + // + // Extract Required to Compile Resources List ... + let compileList = await extractResources(resources, true); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + + // + // Extract Required to Pack Resources List ... + let packList = await extractResources(resources, false); + if (!packList || packList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Pack Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Loop through Files ... + for (const f of packList) { + // + // Prepare Destination Path ... + const fBasePath = XFileTools.basename(f); + let fDestPath = f.replace(fBasePath, ""); + fDestPath = fDestPath.substring(0, fDestPath.length - 1); + fDestPath = XFileTools.joinPath(prjFolderOnPacks, fDestPath); + + // + const isFDestPathExists = XFileTools.isDirectoryExists(fDestPath); + if (!isFDestPathExists) { + XFileTools.createDirectory(fDestPath); + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to copy: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue), + XColorTools.applyForegroundColor(" to : ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(fDestPath, XColorTools.COLOR_NAMES.Magenta) + ); + + // + let result = await XFileTools.copyFile(f, fDestPath); + if (result) { + // + const msg = "copy successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "copy failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Project: ", XColorTools.COLOR_NAMES.Green), + XColorTools.applyForegroundColor(projectName, XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(" Compiled and Packed Successfully ...", XColorTools.COLOR_NAMES.Green), + ); + + // + // Cleanup WorkSpace if Provided ... + if (forceCleanup) { + await cleanupWorkSpace(); + } + + // + // Compile Indicators ... + if (forceCompileIndicators) { + await runCommand("Indicators"); + } +} + +/** + * Extract required Files List ... + * + * @param {boolean} forCompile + * + * @returns Promise + */ +async function extractResources( + resources = [], + forCompile = true +) { + // + let result = []; + + // + // Loop Through Project Resources and Extract Files List to Compile ... + for (const resource of resources) { + // + // Prepare Normalized Resource Path ... + let resourcePath = XFileTools.joinPath(".", resource); + + // + // Handle Wild Card Resources ... + if (resourcePath.endsWith("//*") || + resourcePath.endsWith("\\*")) { + // + resourcePath = resourcePath.substring(0, resourcePath.length - 2); + const files = await XFileTools.extractFiles( + resourcePath, + forCompile ? [".mq5", ".mq4"] : [".ex5", ".ex4"] + ); + + // + result = result.concat(files); + } + // + // Handle Direct File Resources ... + else { + // + // Check MQL 5 Version ... + let fileResourcePath = resourcePath + (forCompile ? ".mq5" : ".ex5"); + + // + // Check File Exists ... + let isExists = XFileTools.isFileExists(fileResourcePath); + if (!isExists) { + // + // Check MQL 4 Version ... + fileResourcePath = resourcePath + (forCompile ? ".mq4" : ".ex4"); + isExists = XFileTools.isFileExists(fileResourcePath); + } + + // + // Add File Path to Files List if Exists ... + if (isExists) { + result.push(fileResourcePath); + } + } + } + + // + return result; +} + +/** + * try to compile a file ... + * @param {string} f + * @param {number} numberOfTries + */ +async function recursiveTriesToCompileFile(f = "", numberOfTries = 0) { + // + let result = await handleFileCompile(f); + if (result) { + // + const msg = "compiled successfully ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green)); + return result; + } else { + // + if (numberOfTries < 10) { + // + numberOfTries++; + + // + const msg = "retry (" + (numberOfTries + 1) + ") ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.LightMagenta)); + await recursiveTriesToCompileFile(f, numberOfTries); + } else { + // + const msg = "failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + + // + return false; + } + } +} + +/** + * execute compile task on Specific File ... + * @param {string} f file path to Execute Compile task ... + * @returns + */ +async function handleFileCompile(f = "") { + // + let result = false; + + // + let exResult = await compileMQLFile(f); + if (exResult.includes("0 errors")) { + result = true; + } else { + result = false; + } + + // + return result; +} + +/** + * Compile Specific MQL File ... + * + * @param {string} path MQL file path ... + * @returns + */ +async function compileMQLFile(path = "") { + // + // Check File Exists ... + const isExists = XFileTools.isFileExists(path); + if (!isExists) { + // + const msg = "file not found ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const ext = XFileTools.getFileExtension(path); + if (ext !== ".mq5" && ext !== "mq4") { + // + const msg = "invalid file extension ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const cwd = __dirname; + const cmd = "compile.cmd " + path; + + // + const result = await XShellTools.execute(cmd, cwd); + return result; +} + +/** + * Run Specified Command in workspace ... + * + * @param {string} cmd + * @returns + */ +async function runCommand(cmd = "") { + // + // Validate Args ... + let isValidArgs = cmd.length > 0 && + XTypeTools.isString(cmd); + + // + // Validate Commands ... + if (isValidArgs) { + // + // Check Available Commands ... + isValidArgs = + cmd === "*" || + cmd === "cleanup" || + workspacePaths.includes(cmd) || + workspacePaths.map(x => x.toLowerCase(x)).includes(cmd.toLowerCase()); + } + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Compile ... + if (cmd == "*") { + await compileWorkSpace(); + } else if (cmd == "cleanup") { + await cleanupWorkSpace(); + } else { + // + // Select Workspace to Compile ... + const folder = workspacePaths + .find(x => x.toLowerCase() === cmd.toLowerCase()); + isValidArgs = + XTypeTools.isString(folder) && + folder.length > 0; + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Extract Required to Compile Resources List ... + let compileList = await XFileTools.extractFiles( + folder, + [".mq5", ".mq4"] + ); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + } +} + +/** + * Cleanup Workspace compiled files ... + */ +async function cleanupWorkSpace() { + // + for (const path of workspacePaths) { + // + const fSourcePath = XFileTools.joinPath(".", path); + const filesToRemove = await XFileTools.extractFiles(fSourcePath, [".ex5", ".ex4"]); + for (const f of filesToRemove) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Remove: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + let result = await XFileTools.removeFile(f); + if (result) { + // + const msg = "removed successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "removed failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + } +} + +/** + * Compile Workspace ... + */ +async function compileWorkSpace() { + // + for (const path of workspacePaths) { + await runCommand(path); + } +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + extractResources, + recursiveTriesToCompileFile, + handleFileCompile, + compileMQLFile, + runCommand, + cleanupWorkSpace, + compileWorkSpace, + prepareProject +} +//#endregion \ No newline at end of file