diff --git a/BKPS/14041018/Classes/x-saherelm.base.class.mq5 b/BKPS/14041018/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..a017ec3 --- /dev/null +++ b/BKPS/14041018/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/14041018/Classes/x-saherelm.x-account.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-account.class.mq5 new file mode 100644 index 0000000..b19c2e2 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-account.class.mq5 @@ -0,0 +1,408 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + XCAccount() + { + // + mAccountInfo = new CAccountInfo(); + } + + // + // Deconstructor ... + ~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; + } + + /** + * Retrieve Specified Message for Report Balance ... + * + * @return ( string ) + */ + string GetBalanceReportMessage() + { + return "Balance: " + ToXString(GetBalance()) + " " + GetCurrency(); + } + + // + // END Provided Functions ... + // + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/BKPS/14041018/Classes/x-saherelm.x-alert.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-alert.class.mq5 new file mode 100644 index 0000000..4c06900 --- /dev/null +++ b/BKPS/14041018/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/14041018/Classes/x-saherelm.x-app-dialog.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-app-dialog.class.mq5 new file mode 100644 index 0000000..fc3de5e --- /dev/null +++ b/BKPS/14041018/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/14041018/Classes/x-saherelm.x-backtester.expert.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-backtester.expert.class.mq5 new file mode 100644 index 0000000..f02d0bf --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-backtester.expert.class.mq5 @@ -0,0 +1,2589 @@ +/////////////////////////////////////////////////////// +// +// 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-guard.class.mq5" +#include "../Classes/x-saherelm.x-position.drawer.class.mq5" +#include "../Classes/x-saherelm.x-target.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 + + // + // 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 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 ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCTrade *eaTrader; // EA Scope Trade Handler ... + XCTarget *eaTarget; // EA Scope Target Manager ... + XCVolume *eaVolume; // EA Scope Volume Manager ... + XCChartHelper *eaChartHelper; // EA Chart Helper ... + XCPositionDrawer *eaPositionDrawer; // EA Scope Position Drawer ... + + // + // 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; + + // + // Chart Helper ... + eaChartHelper = new XCChartHelper(); + + // + // 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]); + } + } + + // + // Signal Executed Event Handlers ... + count = ArraySize(mOnSignalExecutedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnSignalExecutedEventHandler(mOnSignalExecutedEventHandlers[i]); + } + } + + // + // Init Target Managers ... + eaTarget = new XCTarget(eaTrader, eaAlert); + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrader // + ); + + // + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Init Position Drawer ... + eaPositionDrawer = new XCPositionDrawer(eaTrader); + + // + // Initial GUI ... + result = InitGUI(); + if (!result) + { + return result; + } + + // + // Normalize Requirements ... + NormalizeProps(); + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + eaTarget.Destroy(); + delete eaTarget; + ZeroMemory(eaTarget); + + // + if (eaPositionDrawer != NULL) + { + // + eaPositionDrawer.Destroy(); + delete eaPositionDrawer; + ZeroMemory(eaPositionDrawer); + } + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + delete eaTrader; + ZeroMemory(eaTrader); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + 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(); + + // + // Managing Targets ... + eaTarget.Manage(); + + // + // Manage Positions Drawings ... + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.Update(); + } + } + + /** + * 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(); + + // + eaTarget.HandleOnStopLossTriggered(deal); + + // + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.HandleStopLossTriggered(deal); + } + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + // + // Update Position Buttons ... + UpdatePositionButtons(); + + // + eaTarget.HandleOnTakeProfitTriggered(deal); + + // + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.HandleOnTakeProfitTriggered(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 // + ) + { + // + // Update Position Buttons ... + UpdatePositionButtons(); + + // + eaTarget.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); + + // + if (eaPositionDrawer != NULL) + { + // + eaPositionDrawer.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); + } + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + // + // 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 // + ) + { + // + if (eaPositionDrawer != NULL) + { + // + eaPositionDrawer.HandleOnPositionModified( + ticket, + profit, + comment // + ); + } + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + /** + * Handle New Signal Recieved ... + * + * @param signal: XSignal, reference to recieved Signal ... + */ + void HandleOnSignalTriggered(XSignal &signal) + { + // + // Draw Signal ... + XCSignalObject *iSignalObj = new XCSignalObject(); + bool isCreated = iSignalObj.Create( + eaChartHelper.ChartId(), + 0, + signal, + 3 // + ); + if (isCreated) + { + } + + // + // Handle Volume ... + double iVolume = eaVolume.CalculateVolume(signal); + if (!signal.ignoreEAVolume && + iVolume != signal.volume) + { + signal.volume = iVolume; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT result; + bool isExcuted = eaTrader.ExecuteSignal( + signal, + result // + ); + if (isExcuted) + { + } + } + + /** + * Handle Signal Executed Event ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void HandleOnSignalExecuted(XSignal &signal) + { + // + eaTarget.AddExecutedSignal(signal); + + // + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.AddExecutedSignal(signal); + } + } + + // + // 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 // + ); + } + + // + // Add New Signal Executed Event Handler ... + void AddOnSignalExecutedEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalExecutedEventHandlers // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + // Trade Event Listeners ... + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnSignal mOnSignalExecutedEventHandlers[]; + 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 + "_"; + + // + 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 = eaLogSuffix + "_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/14041018/Classes/x-saherelm.x-bar.analyser.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 0000000..a3b0e99 --- /dev/null +++ b/BKPS/14041018/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) ... + XCBarAnalyser() + { + } + + // + // Deconstructor ... + ~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 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 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 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 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 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 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 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 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/14041018/Classes/x-saherelm.x-chart.helper.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-chart.helper.class.mq5 new file mode 100644 index 0000000..b5c3325 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-chart.helper.class.mq5 @@ -0,0 +1,872 @@ +/////////////////////////////////////////////////////// +// +// 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, + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL) + { + // + bool canSetSymbolPeriod = + IsSpecifiedValid(_symbol) && + IsSpecifiedValid(_period); + + // + // Normalize ... + if (!canSetSymbolPeriod) + { + // + mChartID = NormalizeChartId(_chartId); + mSymbol = NormalizeSymbol(_symbol); + mPeriod = NormalizePeriod(_period); + } + else + { + // + SetSymbolPeriod(mSymbol, mPeriod); + } + } + + // + // 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 // + ) + { + bool result = (ChartSetSymbolPeriod(mChartID, symbol, period)); + if (result) + { + // + mSymbol = symbol; + mPeriod = period; + } + + // + return result; + } + + /** + * 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; + } + + ulong Open() + { + // + mChartID = ChartOpen(mSymbol, mPeriod); + return (mChartID); + } + + void Close() + { + // + if (mChartID != -1 && mChartID != 0) + { + ChartClose(mChartID); + mChartID = 0; + } + } + + // + // 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 ... + string mSymbol; // Chart Symbol ... + ENUM_TIMEFRAMES mPeriod; // Chart Period ... +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Classes/x-saherelm.x-cobject.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..6451853 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,2652 @@ +/////////////////////////////////////////////////////// +// +// 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-pivot.analysis.lib.mq5" +#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_EMPTY_OBJ = 7860, // Empty + X_BOX_OBJ = 7861, // XBox + X_BAR_ARROW_OBJ = 7862, // XBarArrow + X_SIGNAL_OBJ = 8860, // XSignal + X_OHCL_OBJ = 8863, // XBar + X_RR_OBJ = 8864, // XRR + X_POSITION_OBJ = 8865, // XPosition + // + // 9860 Custom Object ... +}; + +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; +} + +string ToXString(ENUM_XCHARTOBJECTS value) +{ + // + return EnumToString(value); +} + +struct XPOIStyle +{ + // + // Properties ... + int width; // Width ... + color clr; // Color ... + bool fill; // Fill, Use in Rectangles ... + ENUM_LINE_STYLE style; // Line Style ... + + // + // Constructor ... + XPOIStyle() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup Model ... + void Clean() + { + // + width = 1; + fill = false; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + ZeroMemory(this); + } + + // + // Default Props ... + void Default() + { + // + width = 1; + fill = false; + 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 ToXSignal( + 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; +} + +/** + * Converts a Signal to Position ... + * + * @param signal: XSignal, reference to Specified Signal ... + * @param position: XPosition, reference to Generated Position ... + * @param magic: ulong, Specified Magic Number ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ +bool ToXPosition( + XSignal &signal, + XPosition &position, + ulong magic = 0, + ulong ticket = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + position.Clean(); + + // + // Validate ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Normalize ... + + // + if (ticket <= 0) + { + // + if (signal.positionId > 0) + { + ticket = signal.positionId; + } + else + { + // + ticket = MathRand(); + signal.positionId = ticket; + } + } + signal.positionId = ticket; + + // + if (magic <= 0) + { + magic = MathRand(); + } + + // + // Filling Position ... + position.swap = 0; + position.profit = 0; + position.magic = magic; + position.commission = 0; + position.tp = signal.tp; + position.sl = signal.sl; + position.ticket = ticket; + position.type = signal.type; + position.price = signal.entry; + position.entry = signal.entry; + position.openAt = signal.time; + position.volume = signal.volume; + position.symbol = signal.symbol; + position.period = signal.period; + position.comment = signal.comment; + position.provider = signal.provider; + + // + result = position.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + position.Clean(); + } + + // + return result; +} + +/** + * Update Specified Position by Bar ... + * + * @param position: XPosition, reference to Specified Position ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool XUpdatePosition( + XPosition &position, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = position.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + position.symbol, + position.period, + barIndex // + ); + if (!result) + { + return result; + } + + // + double entryDiff = MathAbs(position.entry - position.price); + bool isLong = IsLong(position.type); + bool isInProfit = isLong + ? position.price > position.entry + : position.price < position.entry; + bool isTargeted = + isLong + ? position.price >= position.tp + : position.price <= position.tp; + bool isStoped = + isLong + ? position.price <= position.sl + : position.price >= position.sl; + result = !isTargeted && !isStoped; + if (!result) + { + return result; + } + + // + double spread = GetSpread(position.symbol); + position.price = bar.close + + (isLong + ? spread + : (-1 * spread)); + entryDiff = MathAbs(position.entry - position.price); + isInProfit = isLong + ? position.price > position.entry + : position.price < position.entry; + result = position.IsValid(); + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + +// +// Implementation ... + +// +// Global Chart Objects ... + +/** + * Base 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) + { + // + Name(value); + mObjName = value; + } + + virtual string TypeString() + { + return ToXString(X_EMPTY_OBJ); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) const + { + return ((int)X_EMPTY_OBJ); + } + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + Detach(); + Delete(); + } + + // + 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 ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mArrow.Detach(); + mArrow.Delete(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_BAR_ARROW_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_BAR_ARROW_OBJ); + } + + // + // 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 Object ... + **/ +class XCSignalObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + XCSignalObject() + { + } + + // + // Deconstructor ... + ~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; + } + + // + // Virtual ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mTPTrend.Detach(); + mTPTrend.Delete(); + mSLTrend.Detach(); + mSLTrend.Delete(); + mEntryTrend.Detach(); + mEntryTrend.Delete(); + + // + mTargetTrends.Clear(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_SIGNAL_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_SIGNAL_OBJ); + } + + // + // 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); + } + + // + 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 = ToXSignal( + box, + signal, + rewardRatios // + ); + if (!result) + { + // + signal.Clean(); + + // + return result; + } + + // + result = Create( + chart_id, + window, + signal, + length, + prefix // + ); + + // + signal.Clean(); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_RR_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_RR_OBJ); + } +}; + +/** + * XOHCL 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; + } + + // + // Virtual ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mBodyRect.Detach(); + mBodyRect.Delete(); + + // + mLowShadowRect.Detach(); + mLowShadowRect.Delete(); + + // + mHighShadowRect.Detach(); + mHighShadowRect.Delete(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_OHCL_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_OHCL_OBJ); + } + + // + // 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); + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mHighShadowRect; + CChartObjectRectangle mBodyRect; + CChartObjectRectangle mLowShadowRect; +}; + +/** + * Box Object ... + **/ +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 = NULL, + 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; + } + + // + // Virtual ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mAt.Detach(); + mAt.Delete(); + + // + mRect.Detach(); + mRect.Delete(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_BOX_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_BOX_OBJ); + } + + // + // 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); + } + + // + private: + // + + // + // Props ... + CChartObjectVLine mAt; + CChartObjectRectangle mRect; +}; + +/** + * Position Object ... + **/ +class XCPositionObject : public XCBaseObject +{ + // + // Public ... + public: + // + XPOIStyle riskStyle; // Risk Box Style ... + color inProfitColor; // In Profit Price Box Color ... + color inDrawdownColor; // In Drawdown Price Box Color ... + XPOIStyle rewardStyle; // Reward Box Style ... + ENUM_LINE_STYLE priceStyle; // Price Box Style ... + + // + // Creators ... + + /** + * Create a Position Object by Signal reference ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param signal: XSignal, reference to Provided Signal ... + * @param magic: ulong, Specified Position Magic Number ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XSignal &signal, + ulong magic = 0, + ulong ticket = 0 // + ) + { + // + bool result = false; + + // + // Converts Signal to Test Position ... + XPosition _position; + result = ToXPosition( + signal, + _position, + magic, + ticket // + ); + + // + // Validate ... + result = chart_id >= 0 && + window >= 0 && + _position.IsValid(); + if (!result) + { + return result; + } + + // + result = Create( + chart_id, + window, + _position // + ); + + // + return result; + } + + /** + * Create a Position Object ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = chart_id >= 0 && + window >= 0 && + position.IsValid(); + if (!result) + { + return result; + } + + // + result = Update(position); + if (!result) + { + // + Destroy(); + return result; + } + + // + return result; + } + + /** + * Update Position if Belongs to ... + * + * @param position: XPosition, reference to Specified Position ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool Update( + XPosition &position, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = + mChartID >= 0 && + mWindowID >= 0 && + position.IsValid() && + (!HasPosition() + ? true + : IsBelong(position)); + if (!result) + { + return result; + } + + // + datetime _toTime = GetBarTime( + position.symbol, + position.period, + barIndex // + ); + + // + // Validate Chart Info ... + result = UpdatePosition( + position, + _toTime // + ); + + // + return result; + } + + /** + * Update Position if Belongs to ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool Update(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + // Update mPosition ... + result = XUpdatePosition(mPosition, barIndex); + if (!result) + { + return result; + } + + // + result = Update( + mPosition, + barIndex // + ); + + // + return result; + } + + // + // Retrievers ... + + bool GetPosition(XPosition &_position) + { + // + bool result = false; + + // + // Prepare ... + _position.Clean(); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + _position = mPosition; + + // + return result; + } + + // + // Checkers ... + + /** + * Check Object is Belongs to Specified Position or not ... + * + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool IsBelong(XPosition &position) + { + // + bool result = false; + + // + // Validate ... + result = + HasPosition() && + position.IsValid(); + + // + // Check ... + result = + result && + mPosition.ticket == position.ticket; + + // + return result; + } + + // + // Overrides ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + string TypeString() override + { + return ToXString(X_POSITION_OBJ); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + int Type(void) const override + { + return ((int)X_POSITION_OBJ); + } + + /** + * Destroy Object ... + **/ + void Destroy() override + { + // + ObjName(NULL); + + // + mRiskBox.Clean(); + mPosition.Clean(); + mPriceBox.Clean(); + mRewardBox.Clean(); + + // + mRiskBoxObj.Detach(); + mRiskBoxObj.Delete(); + + // + mPriceBoxObj.Detach(); + mPriceBoxObj.Delete(); + + // + mRewardBoxObj.Detach(); + mRewardBoxObj.Delete(); + } + + // + // Stylers ... + + /** + * Apply Styles based on Current Style Configurations ... + */ + void ApplyStyle() + { + // + // Validate ... + bool has = HasPosition(); + if (!has) + { + return; + } + + // + // Check Position in Profit ... + bool isLong = IsLong(mPosition.type); + bool isRiskFreed = + isLong + ? mPosition.sl > mPosition.entry + : mPosition.sl < mPosition.entry; + bool isInProfit = mPosition.profit > 0; + XPOIStyle _priceStyle; + if (isInProfit) + { + // + _priceStyle = rewardStyle; + _priceStyle.clr = inProfitColor; + } + else + { + // + _priceStyle = riskStyle; + _priceStyle.clr = inDrawdownColor; + } + + // + // Apply Profit Based Styles ... + _priceStyle.fill = true; + _priceStyle.style = priceStyle; + + // + // Change Risk Style if Risk Freed Position ... + if (isRiskFreed) + { + // + riskStyle.fill = true; + riskStyle.clr = rewardStyle.clr; + } + + // + // Risk Style ... + mRiskBoxObj.BoxColor(riskStyle.clr); + mRiskBoxObj.BoxFill(riskStyle.fill); + mRiskBoxObj.BoxStyle(riskStyle.style); + mRiskBoxObj.BoxWidth(riskStyle.width); + + // + // Reward Style ... + mRewardBoxObj.BoxColor(rewardStyle.clr); + mRewardBoxObj.BoxFill(rewardStyle.fill); + mRewardBoxObj.BoxStyle(rewardStyle.style); + mRewardBoxObj.BoxWidth(rewardStyle.width); + + // + // Price Style .. + mPriceBoxObj.BoxColor(_priceStyle.clr); + mPriceBoxObj.BoxFill(_priceStyle.fill); + mPriceBoxObj.BoxStyle(_priceStyle.style); + mPriceBoxObj.BoxWidth(_priceStyle.width); + + // + // Cleanup Resources ... + _priceStyle.Clean(); + } + + // + void ApplyStyle( + XPOIStyle &bullishStyle, + XPOIStyle &bearishStyle // + ) + { + // + // Validate ... + if (!HasPosition()) + { + return; + } + + // + // Risk Box ... + if (mRiskBox.IsValid()) + { + // + mRiskBoxObj.BoxColor(bearishStyle.clr); + mRiskBoxObj.BoxFill(bearishStyle.fill); + mRiskBoxObj.BoxStyle(bearishStyle.style); + mRiskBoxObj.BoxWidth(bearishStyle.width); + } + + // + // Reward Box ... + if (mRewardBox.IsValid()) + { + // + mRewardBoxObj.BoxColor(bullishStyle.clr); + mRewardBoxObj.BoxFill(bullishStyle.fill); + mRewardBoxObj.BoxStyle(bullishStyle.style); + mRewardBoxObj.BoxWidth(bullishStyle.width); + } + + // + // Price Box ... + if (mPriceBox.IsValid()) + { + // + XPOIStyle _priceStyle; + if (mPriceBox.IsBullish()) + { + _priceStyle = bullishStyle; + } + else + { + _priceStyle = bearishStyle; + } + + // + mPriceBoxObj.BoxColor(_priceStyle.clr); + mPriceBoxObj.BoxFill(_priceStyle.fill); + mPriceBoxObj.BoxStyle(_priceStyle.style); + mPriceBoxObj.BoxWidth(_priceStyle.width); + + // + _priceStyle.Clean(); + } + } + + // + // Protected ... + protected: + // + + // + bool HasPosition() + { + return mPosition.IsValid(); + } + + // + bool UpdatePosition( + XPosition &_position, + datetime _toTime = NULL // + ) + { + // + bool result = false; + + // + // Normalize ... + _toTime = NormalizeTime(_toTime); + + // + // Validate ... + result = _position.IsValid() && + (!HasPosition() + ? true + : _position.ticket == mPosition.ticket // + ); + if (!result) + { + return result; + } + + // + mPosition = _position; + result = UpdateZones(_toTime); + + // + return result; + } + + // + bool UpdateZones(datetime _toTime = NULL) + { + // + bool result = false; + + // + // Normalize ... + _toTime = NormalizeTime(_toTime); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + string iSymbol = mPosition.symbol; + ENUM_TIMEFRAMES iPeriod = mPosition.period; + + // + datetime iAt = mPosition.openAt; + datetime iFrom = mPosition.openAt; + + // + datetime _defaultToTime = iFrom + (PeriodSeconds(iPeriod) * 3); + datetime iTo = _toTime <= _defaultToTime + ? _defaultToTime + : _toTime; + + // + double iTP = mPosition.tp; + double iSL = mPosition.sl; + double iEntry = mPosition.entry; + double iPrice = mPosition.price; + + // + bool isLong = IsLong(mPosition.type); + ENUM_X_DIRECTION iRiskDir = isLong + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + ENUM_X_DIRECTION iRewardDir = isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + bool isInProfit = mPosition.profit > 0; + bool isRiskFreed = + isLong + ? mPosition.sl > mPosition.entry + : mPosition.sl < mPosition.entry; + ENUM_X_DIRECTION iPriceDir = isInProfit + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Try to Update Zones ... + string iSuffix = ToXString(mPosition.type) + "_" + ToXString(mPosition.ticket); + string iPrefix = ToXString(TimeToSeconds(mPosition.openAt)); + string iName = iSuffix + "_" + iPrefix; + string iRiskName = iSuffix + "_" + "RISK" + "_" + iPrefix; + string iPriceName = iSuffix + "_" + "PRICE" + "_" + iPrefix; + string iRewardName = iSuffix + "_" + "REWARD" + "_" + iPrefix; + + // + // Risk Box ... + mRiskBox.to = iTo; + mRiskBox.at = iAt; + mRiskBox.lower = + isLong + ? isRiskFreed + ? iEntry + : iSL + : isRiskFreed + ? iSL + : iEntry; + mRiskBox.upper = + isLong + ? isRiskFreed + ? iSL + : iEntry + : isRiskFreed + ? iEntry + : iSL; + mRiskBox.from = iFrom; + mRiskBox.symbol = iSymbol; + mRiskBox.period = iPeriod; + mRiskBox.type = iRiskName; + mRiskBox.dir = isRiskFreed + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + + // + // Reward Box ... + mRewardBox.to = iTo; + mRewardBox.at = iAt; + mRewardBox.lower = + isLong + ? iEntry + : iTP; + mRewardBox.upper = + isLong + ? iTP + : iEntry; + mRewardBox.from = iFrom; + mRewardBox.symbol = iSymbol; + mRewardBox.period = iPeriod; + mRewardBox.type = iRewardName; + mRewardBox.dir = X_DIRECTION_BULLISH; + + // + // Price Box ... + mPriceBox.to = iTo; + mPriceBox.at = iAt; + mPriceBox.lower = + isLong + ? isInProfit + ? isRiskFreed + ? iSL + : iEntry + : iPrice + : isInProfit + ? isRiskFreed + ? iSL + : iPrice + : iEntry; + mPriceBox.upper = + isLong + ? isInProfit + ? iPrice + : iEntry + : isInProfit + ? iEntry + : iPrice; + mPriceBox.from = iFrom; + mPriceBox.symbol = iSymbol; + mPriceBox.period = iPeriod; + mPriceBox.type = iPriceName; + mPriceBox.dir = isInProfit + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = mRiskBox.IsValid() && + mPriceBox.IsValid() && + mRewardBox.IsValid(); + if (!result) + { + return result; + } + + // + mRiskBoxObj.Detach(); + mRiskBoxObj.Delete(); + bool isRiskCreated = + mRiskBoxObj.Create( + mChartID, + mWindowID, + mRiskBox.type, + mRiskBox.upper, + mRiskBox.lower, + mRiskBox.from, + mRiskBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + mRewardBoxObj.Detach(); + mRewardBoxObj.Delete(); + bool isRewardCreated = + mRewardBoxObj.Create( + mChartID, + mWindowID, + mRewardBox.type, + mRewardBox.upper, + mRewardBox.lower, + mRewardBox.from, + mRewardBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + mPriceBoxObj.Detach(); + mPriceBoxObj.Delete(); + bool isPriceCreated = + mPriceBoxObj.Create( + mChartID, + mWindowID, + mPriceBox.type, + mPriceBox.upper, + mPriceBox.lower, + mPriceBox.from, + mPriceBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + result = + isRiskCreated && + isPriceCreated && + isRewardCreated; + if (result) + { + // + ObjName(iName); + + // + // Apply Styles ... + ApplyStyle(); + } + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + int mWindowID; + long mChartID; + + // + XBoxZone mRiskBox; + XBoxZone mPriceBox; + XPosition mPosition; + XBoxZone mRewardBox; + + // + XCBoxObject mRiskBoxObj; + XCBoxObject mPriceBoxObj; + XCBoxObject mRewardBoxObj; + + // +}; + +// +// Extensions ... + +/** + * Add all Items of Specified CArrayObj into another ... + * + * @param source: CArrayObj, pointer refrence Specified Data Source ... + * @param dest: CArrayObj, pointer refrence Specified Destination of Adding ... + */ +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)); + } +} + +/** + * Remove Drawn Objects from Chart ... + * + * @param tag: Specified Object Name, if NULL remove all Objects ... + * @param chartId: long, Specified Chart ... + * @param subWindow: int Specified Sub Window ... + */ +void RemoveObjects( + string tag = NULL, + long chartId = -1, + int subWindow = -1 // +) +{ + // + // Normalize Args ... + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + bool has = false; + string iName = NULL; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + // Retrieve Object Name ... + iName = ObjectName(chartId, iObj, subWindow); + + // + // Check Can Delete Object or not ... + has = + !IsSpecifiedValid(tag) + ? true + : StringFind(iName, tag) >= 0; + if (has) + { + ObjectDelete(chartId, iName); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +// Color Manipulation Functions ... + +/** + * Apply Alph to Color ... + * + * @param _clr: Specified Color ... + * @param _alpha: Specified Alpha to Apply ... + * + * @return ( color ) + */ +color ApplyAlpha( + color _clr, + uchar _alpha = 255 // +) +{ + // + color result = _clr; + + // + // Normalize ... + _alpha = (uchar)NormalizeInt(_alpha, 0, 255); + + // + uchar alpha = _alpha / 255; + + // + uint uintColor = ColorToARGB(_clr, alpha); + result = (color)uintColor; + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Classes/x-saherelm.x-data.collector.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-data.collector.class.mq5 new file mode 100644 index 0000000..fb45c04 --- /dev/null +++ b/BKPS/14041018/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/14041018/Classes/x-saherelm.x-expert.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-expert.class.mq5 new file mode 100644 index 0000000..59e4d1a --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-expert.class.mq5 @@ -0,0 +1,2909 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCBaseExpret ... +// Description: Base Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Base Expert Class" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.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-guard.class.mq5" +#include "../Classes/x-saherelm.x-position.drawer.class.mq5" +#include "../Classes/x-saherelm.x-signaller.class.mq5" +#include "../Classes/x-saherelm.x-target.class.mq5" +#include "../Classes/x-saherelm.x-trade-manager.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" + +// +// Import Chart Objects ... +#include +#include +#include +#include + +// +// Definitions ... + +// +// Implementation ... +class XCBaseExpert : 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 + + // + // GUI Management Panel ... + bool eaShowPanel; // Show Management Panel + double eaPanelAllowedTPSLStep; // Value for Change TP/SL in Each Step + double eaPanelMinAllowedRiskInPoint; // Min Allowed Risk in Point + double eaPanelRiskInPoint; // Risk in Point per Trades + double eaPanelRiskToRewardRatio; // Risk To Reward per Trades + double eaPanelVolume; // Default volume Per Trade + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCTrade *eaTrader; // EA Scope Trade Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XCTarget *eaTarget; // EA Scope Target Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + XCTradeManager *eaTradeManager; // EA Scope Trade Manager Handler ... + XCPositionDrawer *eaPositionDrawer; // EA Scope Position Drawer ... + + // + // Specified Event Handlers ... + TOnGuarded onGuardedEventHandler; + TCanAnalyse canAnalyseEventHandler; + TCheckForGuard checkForGuardEventHandler; + + // + // Tools / 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.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 ... + eaTrader = 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++) + { + 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]); + } + } + + // + // Signal Executed Event Handlers ... + count = ArraySize(mOnSignalExecutedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnSignalExecutedEventHandler(mOnSignalExecutedEventHandlers[i]); + } + } + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrader // + ); + + // + // Attach Event Handler ... + eaGuard.onGuardEventListener = onGuardedEventHandler; + + // + // Initialize Target Handler ... + eaTarget = new XCTarget(eaTrader, eaAlert); + + // + // Init Position Drawer ... + eaPositionDrawer = new XCPositionDrawer(eaTrader); + + // + // Initialize Trae Manager ... + eaTradeManager = new XCTradeManager( + eaAlert, + eaTrader, + eaVolume, + eaGuard, + eaTarget // + ); + + // + // 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) + { + // + // Configure Signallers ... + for (int i = 0; i < count; i++) + { + // + // Register Signallers ... + PrepareSignallers(symbolConfigurations[i]); + } + } + SpecifiedClean(symbolConfigurations); + + // + result = InitPanel(); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + DestroyPanel(); + + // + delete eaTrader; + ZeroMemory(eaTrader); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + eaTarget.Destroy(); + delete eaTarget; + ZeroMemory(eaTarget); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + eaPositionDrawer.Destroy(); + delete eaPositionDrawer; + ZeroMemory(eaPositionDrawer); + + // + 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() + { + // + // Update GUI Panel ... + UpdatePanel(); + + // + // Time Report ... + HandleTimeReport(); + + // + // Manage Trades ... + eaTradeManager.Manage(); + + // + // Manage Positions Drawings ... + eaPositionDrawer.Update(); + + // + 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].OnTick(0); + } + + // + HandleOnTickAdditional(); + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + eaTrader.HandleOnTrade(); + } + + /** + * Handle Timer ... + */ + void virtual 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 virtual HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Event Triggered Listeners ... + + /** + * Handle New Signal Recieved ... + * + * @param signal: XSignal, Recieved Signal ... + */ + void HandleOnSignalTriggered(XSignal &signal) + { + eaTradeManager.HandleSignal(signal); + } + + /** + * Handle Signal Executed Event ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void HandleOnSignalExecuted(XSignal &signal) + { + // + eaPositionDrawer.AddExecutedSignal(signal); + eaTradeManager.target.AddExecutedSignal(signal); + } + + /** + * Check For Guard ... + * + * @param guards: XGuard, reference Collection to holds result ... + * @param positions: XPosition, refrence collection to Provides Positions ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( int ) + */ + int CheckForGuardTriggered( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + 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, + positions, + barIndex // + ); + 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 Market based on Time ... + * + * @param symbol: string, Specified Symbol ... + * @param period: ENUM_TIMEFRAMES, Specified Period ... + * @param time: datetime, Specified Time ... + * + * @return ( bool ) + */ + 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 virtual HandleOnStopLossTriggered(const XDeal &deal) + { + // + eaTradeManager.HandleSL(deal); + eaPositionDrawer.HandleStopLossTriggered(deal); + UpdatePanelPositionButtons(); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void virtual HandleOnTakeProfitTriggered(const XDeal &deal) + { + // + UpdatePanelPositionButtons(); + eaTradeManager.HandleTP(deal); + eaPositionDrawer.HandleOnTakeProfitTriggered(deal); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void virtual HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + // + UpdatePanelPositionButtons(); + eaTradeManager.HandleForceClose(position); + eaPositionDrawer.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void virtual 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 virtual 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 virtual 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 virtual HandleOnPositionsChanged(int count) + { + UpdatePanelPositionButtons(); + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void virtual HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + eaPositionDrawer.HandleOnPositionModified( + ticket, + profit, + comment // + ); + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void virtual HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool virtual ValidateInputs() + { + // + bool result = false; + + // + // TODO: Handle this ... + result = true; + + // + return result; + } + + // + // Viruals ... + + /** + * Prepare Signallers per Symbol Config ... + * + * @param symbolConfig: XSymbolTradeConfig, Symbol Trade Configurations ... + */ + void virtual PrepareSignallers(XSymbolTradeConfig &symbolConfig) + { + } + + /** + * Additional On Tick Processing if Required ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void virtual HandleOnTickAdditional(int barIndex = 0) + { + } + + // + // Signal Event Handlers ... + + // + void AddOnSignalEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalEventHandlers // + ); + } + + // + // Add New Signal Executed Event Handler ... + void AddOnSignalExecutedEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalExecutedEventHandlers // + ); + } + + // + // 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 + // + ); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Actions and Tools ... + + /** + * 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(XCBaseSignaller *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 ... + + // + // Specified Event Handlers ... + TOnModify mOnModifyEventHandlers[]; + TOnSignal mOnSignalEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnSignal mOnSignalExecutedEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + XCBaseSignaller *eaSignallers[]; // All Registered Signallers ... + + // + // Panel Support ... + + // + XCChartHelper *eaChartHelper; // Chart Helper Class ... + + // + 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; + + /** + * Initial Management GUI Panel ... + * + * @return ( bool ) + */ + bool InitPanel() + { + // + bool result = false; + + // + result = !eaShowPanel; + if (result) + { + return result; + } + + // + // Check Default Symbol and Period ... + + // + 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); + } + + // + UpdatePanelState(); + + // + return result; + } + + /** + * Listen For Panel Controls Events and + * Update State of GUI Panel ... + */ + void UpdatePanel() + { + // + if (!eaShowPanel) + { + return; + } + + // + UpdatePanelState(); + + // + // 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; + UpdatePanelState(); + } + } + + // + iBtn.Pressed(false); + } + + // + ZeroMemory(iBtn); + } + } + } + + /** + * Update GUI Panels Controls States ... + */ + void UpdatePanelState() + { + // + if (!eaShowPanel) + { + return; + } + // + // 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 Panel's Position Selector Buttons ... + */ + void UpdatePanelPositionButtons() + { + // + if (!eaShowPanel) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = eaTrader.GetPositions( + positions // + ); + bool has = IsValidSize(count); + if (!has) + { + // + posArray.Clear(); + selectedPositionID = 0; + UpdatePanelState(); + 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); + UpdatePanelState(); + + // + } + + /** + * Destroy Management GUI Panel ... + */ + void DestroyPanel() + { + // + delete eaChartHelper; + ZeroMemory(eaChartHelper); + + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + + // + void NormalizePanelProps() + { + // + if (eaPanelVolume < 0.01) + { + eaPanelVolume = 0.01; + } + + // + if (eaPanelRiskInPoint < 0) + { + eaPanelRiskInPoint = 50; + } + + // + if (eaPanelAllowedTPSLStep < 5) + { + eaPanelAllowedTPSLStep = 5; + } + + // + if (eaPanelRiskToRewardRatio < 0.5) + { + eaPanelRiskToRewardRatio = 2; + } + + // + if (eaPanelMinAllowedRiskInPoint < 10) + { + eaPanelMinAllowedRiskInPoint = 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; + } + + // + // Management Panel Event Handlers ... + + // + void HandleBuyTrade() + { + HandleTrade(X_DIRECTION_BULLISH); + } + + // + void HandleSellTrade() + { + HandleTrade(X_DIRECTION_BEARISH); + } + + // + void HandleTrade(ENUM_X_DIRECTION dir) + { + // + if (!HasDirection(dir)) + { + return; + } + + // + NormalizePanelProps(); + + // + bool isBullish = IsSpecifiedBullish(dir); + + // + double _volume = eaPanelVolume; + double r2r = eaPanelRiskToRewardRatio; + double _riskInPoints = eaPanelRiskInPoint; + double point = GetPoints(eaChartHelper.Symbol()); + double entry = GetEntry(eaChartHelper.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 = eaLogSuffix + "_POS_" + ToXString(dir); + + // + if (isBullish) + { + // + eaTrader.Buy( + eaChartHelper.Symbol(), + eaChartHelper.Period(), + _volume, + entry, + sl, + tp, + comment // + ); + } + else + { + // + eaTrader.Sell( + eaChartHelper.Symbol(), + eaChartHelper.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; + } + + // + NormalizePanelProps(); + + // + // 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 * eaPanelAllowedTPSLStep); + + // + 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) + { + UpdatePanelState(); + } + + // + position.Clean(); + } + + // + void HandleSLChange( + ENUM_X_DIRECTION dir, + int multiplier = 1 // + ) + { + // + // Validate ... + if (selectedPositionID == 0 || !HasDirection(dir)) + { + return; + } + + // + NormalizePanelProps(); + + // + // 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 * eaPanelAllowedTPSLStep); + + // + bool mustIncrease = + isBullish + ? !isLong + : isLong; + + // + double risk = position.GetRiskInPoint(); + if (risk <= eaPanelMinAllowedRiskInPoint) + { + // + 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) + { + UpdatePanelState(); + } + + // + position.Clean(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Classes/x-saherelm.x-guard.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-guard.class.mq5 new file mode 100644 index 0000000..ca2a63f --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-guard.class.mq5 @@ -0,0 +1,1973 @@ +/////////////////////////////////////////////////////// +// +// 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.sl <= 0 + ? guard.force + : true) && + guard.action == X_GUARD_ACTION_TRAIL_STOP; + if (!has) + { + return; + } + + // + // Normalize SL ... + if (guard.sl < 0) + { + guard.sl = 0; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + bool isLong = IsLong(position.type); + bool isGuardPassed = + guard.sl > 0 + ? (isLong + ? position.price > guard.sl && + (position.sl == 0 || + position.sl < guard.sl) + : position.price < guard.sl && + (position.sl == 0 || + position.sl > guard.sl)) + : (guard.sl == 0 && guard.force); + + // + // 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 ... + isGuardPassed; + 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.tp <= 0 + ? guard.force + : true) && + guard.action == X_GUARD_ACTION_TRAIL_TARGET; + if (!has) + { + return; + } + + // + // Normalize ... + if (guard.tp < 0) + { + guard.tp = 0; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + bool isLong = IsLong(position.type); + bool isGuardPassed = + guard.tp > 0 + ? (isLong + ? guard.tp > position.price + : guard.tp < position.price) + : (guard.tp == 0 && guard.force); + + // + // 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 ... + isGuardPassed; + 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/14041018/Classes/x-saherelm.x-helper.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-helper.class.mq5 new file mode 100644 index 0000000..b2bf736 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-helper.class.mq5 @@ -0,0 +1,671 @@ +/////////////////////////////////////////////////////// +// +// 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" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +// a Class for Handle base requirements ... +// for indicators ... +class XCBaseHelper : public XCBase +{ + // + // Public ... + public: + // + // Constructor ... + XCBaseHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) + { + // + mSymbol = symbol; + mPeriod = period; + } + + // + // Deconstructor ... + ~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 ... + + /** + * Validate Handler Exists ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsXValid(mSymbol) && + IsXValid(mPeriod) && + mHandler != INVALID_HANDLE; + + // + return result; + } + + /** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ + int ExtractBarZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + XOHCL bar; + bool has = false; + + // + // Initialized Start Bar ... + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone zone; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + bool lowShadowPassed = false; + bool highShadowPassed = false; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + iBar.Clean(); + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + has = bar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Check Direction ... + isBullish = iBar.open < iBar.close; + isBearish = iBar.open > iBar.close; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Low Shadow ... + lowShadowPassed = iBar.GetLowShadow() >= (shadowMultiplier * iBar.GetHighShadow()); + + // + // High Shadow ... + highShadowPassed = iBar.GetHighShadow() >= (shadowMultiplier * iBar.GetLowShadow()); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? iBar.GetDown() + : IsXBearish(zone.dir) + ? iBar.high + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? iBar.low + : IsXBearish(zone.dir) + ? iBar.GetUp() + : EMPTY_VALUE; + + // + zone.to = bar.time; + zone.type = "XBar_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : "") + + "_" + ToXString(TimeToSeconds(zone.from)); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? bar.low > zone.upper + : bar.high < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateBarZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iBar.Clean(); + zone.Clean(); + + // + return result; + } + + /** + * Validate Bar Zone ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param validationLength: int, Validation Length of Zones ... + * @param breakValidLength: int, Break Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * + * @return ( bool ) + */ + bool ValidateBarZone( + XBoxZone &zone, + int validationLength = 1, + int breakValidLength = 3, + bool validateFakeBreakes = true // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + breakValidLength = NormalizeInt(breakValidLength, 2); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Requirements ... + XOHCL iBar; + int count = 0; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int start = zone.FromIndex() + 1; + int end = start + validationLength; + + // + // Validate Before ... + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + symbol, + period, + i // + ); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? iBar.low > zone.lower + : iBar.high < zone.upper; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = start; i < end; i++) + { + // + // Initialized Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + symbol, + period, + i // + ); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? iBar.low > zone.lower + : iBar.high < zone.upper; + if (!result) + { + // + // Check For Fake Breake ... + if (validateFakeBreakes && breakValidLength > 0) + { + // + result = i - 1 >= 0; + if (result) + { + // + for (int j = i - 1; j >= zone.ToIndex(); j--) + { + // + // Initialized Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + symbol, + period, + j // + ); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? iBar.close > zone.upper + : iBar.close < zone.lower; + if (result) + { + // + result = MathAbs(j - i) <= breakValidLength; + if (result) + { + break; + } + } + } + } + } + + // + if (!result) + { + break; + } + } + } + } + + // + // Cleanup Resource ... + iBar.Clean(); + + // + return result; + } + + /** + * Normalizing Bar Index ... + * + * @param barIndex: int, Provided Bar Index ... + * + * @return ( int ) + */ + int NormalizeBarIndex(int barIndex) + { + // + int result = barIndex; + + // + if (!IsValid()) + { + return result; + } + + // + int count = CountBars() - 1; + result = NormalizeInt(result, 0, count - 1); + + // + return result; + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Indicator Handler ... + int mHandler; + + /** + * Read Value of Specified Buffer ... + * + * @param bufferIndex: int, which handler buffer to read value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( double ) + */ + double ReadValue( + int bufferIndex, + int barIndex = 0 // + ) + { + // + double result = EMPTY_VALUE; + + // + // Normalize ... + int barsTotal = CountBars(); + barIndex = NormalizeInt(barIndex, 0, barsTotal - 1); + bufferIndex = NormalizeInt(bufferIndex, 0); + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + double tmp[]; + int count = CopyBuffer( + mHandler, + bufferIndex, + barIndex, + 1, + tmp // + ); + result = tmp[0]; + + // + return result; + } + + /** + * Read Values of Specified Buffer ... + * + * @param buffer: double, reference collection to holds result ... + * @param bufferIndex: int, which handler buffer to read value ... + * @param barIndex: int, Specified Bar Index ... + * @param count: int, number of items to read, 0 for WHOLE_ARRAY ... + * @param asSeries: bool, set As Series Buffer or not ... + * + * @return ( int ) + */ + int ReadValues( + double &buffer[], + int bufferIndex, + int barIndex = 0, + int count = 0, + bool asSeries = true // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(buffer); + + // + // Normalize ... + int barsTotal = CountBars(); + count = NormalizeInt(count, 0); + bufferIndex = NormalizeInt(bufferIndex, 0); + barIndex = NormalizeInt(barIndex, 0, barsTotal - 1); + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + result = CopyBuffer( + mHandler, + bufferIndex, + barIndex, + count, + buffer // + ); + + // + // Set As Series Flag ... + ArraySetAsSeries(buffer, asSeries); + + // + result = ArraySize(buffer); + + // + return result; + } + + // + // Private ... + private: + // +}; + +// +// Tools .... \ No newline at end of file diff --git a/BKPS/14041018/Classes/x-saherelm.x-http.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-http.class.mq5 new file mode 100644 index 0000000..88c2185 --- /dev/null +++ b/BKPS/14041018/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 ... + XCHttp() + { + XCHttp("", 10000); + } + XCHttp( + string path, // Base Folder to Store Data + int timeout // base timeout for Requests + ) + { + // + Path(path); + Timeout(timeout); + } + + // + // Deconstructor ... + ~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/14041018/Classes/x-saherelm.x-market.pattern.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-market.pattern.class.mq5 new file mode 100644 index 0000000..826d1c5 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -0,0 +1,4887 @@ +/////////////////////////////////////////////////////// +// +// 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" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCMarketPatternDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCMarketPatternDetector() + { + barAnalyser = new XCBarAnalyser(); + } + + // + // Deconstructor ... + ~XCMarketPatternDetector() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Analysers ... + + /** + * Check for Price Touch Support Level ... + * + * @param bar: XOHCL, Specified Bar ... + * @param supportBar: XOHCL, reference to holds Zone Bar ... + * @param supportBox: XBoxZone, reference to holds Zone Box ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool IsSupportTouched( + XOHCL &bar, + XOHCL &supportBar, + XBoxZone &supportBox, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + supportBar.Clean(); + supportBox.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Support Exists ... + result = HasSupport( + bar, + supportBar, + validationLength, + maxAllowedLoopback // + ); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + // Extract Support Box ... + result = ToSupportBox( + supportBar, + supportBox // + ); + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = + result && + bar.GetPreviousBar(pBar); + + // + // Chekc Price of Bar ... + result = + result && + pBar.low < supportBox.upper; + + // + // Cleanup Resources ... + if (!result) + { + // + supportBar.Clean(); + supportBox.Clean(); + } + pBar.Clean(); + + // + return result; + } + + /** + * Check for Price Touch Resistance Level ... + * + * @param bar: XOHCL, Specified Bar ... + * @param supportBar: XOHCL, reference to holds Zone Bar ... + * @param supportBox: XBoxZone, reference to holds Zone Box ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool IsResistanceTouched( + XOHCL &bar, + XOHCL &resistanceBar, + XBoxZone &resistanceBox, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + resistanceBar.Clean(); + resistanceBox.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Resistance Exists ... + result = HasResistance( + bar, + resistanceBar, + validationLength, + maxAllowedLoopback // + ); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + // Extract Resistance Box ... + result = ToResistanceBox( + resistanceBar, + resistanceBox // + ); + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = + result && + bar.GetPreviousBar(pBar); + + // + // Chekc Price of Bar ... + result = + result && + pBar.high > resistanceBox.lower; + + // + // Cleanup Resources ... + if (!result) + { + // + resistanceBar.Clean(); + resistanceBox.Clean(); + } + pBar.Clean(); + + // + return result; + } + + // + // Detectors ... + + /** + * Check Specified Bar is Peak or Vale ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ + bool IsPV( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int validationLength = 7, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, // + ENUM_X_PRICE valePriceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 2); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(peakPriceType) && + IsXValid(valePriceType); + if (!result) + { + return result; + } + + // + int valeIndex = -1; + double vale = bar.FindLowest( + valeIndex, + validationLength, + valePriceType // + ); + double barVale = bar.GetPrice(valePriceType); + bool isVale = + NotEmptyZero(vale) && + NotEmptyZero(barVale) && + IsValidIndex(valeIndex) && + vale >= barVale; + + // + int peakIndex = -1; + double peak = bar.FindHighest( + peakIndex, + validationLength, + peakPriceType // + ); + double barPeak = bar.GetPrice(peakPriceType); + bool isPeak = + NotEmptyZero(peak) && + NotEmptyZero(barPeak) && + IsValidIndex(peakIndex) && + peak <= barPeak; + + // + result = (isVale && !isPeak) || + (isPeak && !isVale); + if (result) + { + // + dir = + isVale + ? X_DIRECTION_BULLISH + : isPeak + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + + // + return result; + } + + /** + * 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: double, a Multipler for approve Momentum ... + * + * @return ( bool ) + */ + bool IsMomentumBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int requiredBars = 3, + double approvedMultiplier = 2 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + requiredBars = NormalizeInt(requiredBars, 3, 10); + approvedMultiplier = NormalizeDouble(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: double, 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, + double shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + shadowApprovedMultiplier = NormalizeDouble(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 IsStarPattern( + 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 ... + * + * @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: double, 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, + double 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; + } + + /** + * Check Specified Bar has Pullback Bar Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param pullbackLength: int, min required indirectional bars to confirm pullback ... + * @param forceBreak: bool, force pullback bar breaks peak or vale of Zone ... + * + * @return ( bool ) + */ + bool IsPullbackPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int pullbackLength = 2, + bool forceBreak = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + pullbackLength = NormalizeInt(pullbackLength, 2); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // First Bar Direction ... + dir = bar.GetDirection(); + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Loop through Pullback Length ... + XOHCL iBar; + datetime from = NULL; + double max = EMPTY_VALUE; + double min = EMPTY_VALUE; + int start = bar.Index() + 1; + int end = start + pullbackLength; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + result = bar.BarAt(i, iBar) && + iBar.GetDirection() == Opposit(dir); + if (!result) + { + break; + } + + // + // Calculate Max and Min ... + max = + !NotEmptyZero(max) + ? iBar.high + : MathMax(max, iBar.high); + min = + !NotEmptyZero(min) + ? iBar.low + : MathMin(min, iBar.low); + from = iBar.time; + } + + // + // Apply Force Break ... + if (result && + forceBreak) + { + // + result = + result && + NotEmptyZero(min) && + NotEmptyZero(max) && + (IsXBullish(dir) + ? bar.close > max + : bar.close < min); + } + + // + // Prepare Zone ... + if (result) + { + // + ToBox( + bar, + zone, + dir, + ToXString(X_BAR_PATTERN_PULLBACK) // + ); + zone.upper = max; + zone.lower = min; + zone.from = from; + zone.at = bar.time; + zone.to = bar.time; + + // + result = zone.IsValid(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + /** + * Check Market Has Consolidation Pattern or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param validationLength: int, Validation Length ... + * @param breakPriceType: ENUM_X_PRICE, Specified Price Type to Breake Consolidation ... + * @param upperPriceType: ENUM_X_PRICE, Specified Price Type to Detected Upper of Consolidation ... + * @param lowerPriceType: ENUM_X_PRICE, Specified Price Type to Detected Lower of Consolidation ... + * + * @return ( bool ) + */ + bool IsConsolidationPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int validationLength = 5, + ENUM_X_PRICE breakPriceType = X_PRICE_CLOSE, + ENUM_X_PRICE upperPriceType = X_PRICE_HIGH, + ENUM_X_PRICE lowerPriceType = X_PRICE_LOW // + ) + { + // + // Descriptions: + // =============== + // Consolidation Zones Happens by Highest High and Lowest Low + // of Specified Range which Breakes From one Side ... + // + + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(lowerPriceType) && + IsXValid(upperPriceType) && + IsXValid(breakPriceType); + if (!result) + { + return result; + } + + // + // Define Requirements ... + XOHCL iBar; + bool has = false; + datetime to = NULL; + datetime from = NULL; + double iLow = EMPTY_VALUE; + bool hasLowShadow = false; + double lower = EMPTY_VALUE; + double upper = EMPTY_VALUE; + double iHigh = EMPTY_VALUE; + bool hasHighShadow = false; + double iPrice = EMPTY_VALUE; + bool isLowerBreaked = false; + bool isUpperBreaked = false; + + // + // Loop Through Bars ... + int barIndex = bar.Index(); + int idx = barIndex; + bool canLookup = IsValidIndex(idx); + while (canLookup) + { + // + // Initialize Indexed Bar ... + idx++; + iBar.Clean(); + result = bar.BarAt(idx, iBar); + if (!result) + { + break; + } + + // + // Update Time ... + if (idx == barIndex + 1) + { + to = iBar.time; + } + + // + // Extract Low and High Price ... + iLow = iBar.GetPrice(lowerPriceType); + iHigh = iBar.GetPrice(upperPriceType); + result = NotEmptyZero(iLow) && + NotEmptyZero(iHigh); + if (!result) + { + break; + } + + // + // Check Bar Has Low/High Shadow ... + hasLowShadow = iBar.GetLowShadow() > iBar.GetHighShadow(); + hasHighShadow = iBar.GetHighShadow() > iBar.GetLowShadow(); + + // + // Update Range Lower and Upper based on Shadows ... + + // + // Lower ... + if (hasLowShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(lower) + ? true + : iLow < lower; + if (has) + { + lower = iLow; + } + } + + // + // Upper ... + if (hasHighShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(upper) + ? true + : iHigh > upper; + if (has) + { + upper = iHigh; + } + } + + // + // Check Price Breakes ... + iPrice = iBar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + if (!result) + { + break; + } + + // + // Check Upper/Lower breakes ... + isLowerBreaked = iPrice < lower; + isUpperBreaked = iPrice > upper; + + // + canLookup = (!isLowerBreaked && !isUpperBreaked); + if (!canLookup) + { + break; + } + + // + from = iBar.time; + } + + // + // Validate Calculations ... + result = + // + IsXValid(to) && + IsXValid(from) && + from < to && + // + NotEmptyZero(lower) && + NotEmptyZero(upper) && + upper > lower + // + ; + + // + // Validate To Edge Breakes ... + if (result) + { + // + iPrice = bar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + + // + // Validate To Edge Breakes ... + if (result) + { + // + isUpperBreaked = iPrice > upper; + isLowerBreaked = iPrice < lower; + + // + // Validate To Break ... + result = isUpperBreaked || isLowerBreaked; + } + + // + // Prepare Direction ... + if (result) + { + // + dir = + isUpperBreaked + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Validate Direction ... + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.to = to; + zone.dir = dir; + zone.from = from; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Validate Zone ... + result = zone.IsValid(); + + // + // Validate Zone Length ... + if (result) + { + result = zone.FromIndex() - zone.ToIndex() >= validationLength; + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + bool HasCandlestickDirection( + XOHCL &bar, + ENUM_X_DIRECTION forDir, + bool checkStarPattern = true, + bool checkPinBarPattern = true, + bool checkPiercingPattern = true, + bool checkEngulfedPattern = true, + bool checkMomentumPattern = true, + bool checkSignalKeyBarPattern = true // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION tmpDir = X_DIRECTION_NONE; + + // + // Star ... + bool isStarPattern = false; + if (checkStarPattern) + { + // + isStarPattern = + IsStarPattern(bar, tmpDir) && + tmpDir == forDir; + } + + // + bool isPiercingPattern = false; + if (checkPiercingPattern) + { + // + isPiercingPattern = + IsPiercingPattern(bar, tmpDir) && + tmpDir == forDir; + } + + // + // Engulfed ... + bool isEngulfedPattern = false; + if (checkEngulfedPattern) + { + // + isEngulfedPattern = + IsEngulfedBar(bar, tmpDir) && + tmpDir == forDir; + } + + // + // PinBar ... + bool isPinBarPattern = true; + if (checkPinBarPattern) + { + // + isPinBarPattern = + IsPinnedBar(bar, tmpDir) && + tmpDir == forDir; + } + + // + // Signal Key Bar ... + bool isSignalKeyBarPattern = false; + if (checkSignalKeyBarPattern) + { + // + isSignalKeyBarPattern = + IsSignalKeyBarPattern(bar, tmpDir) && + tmpDir == forDir; + } + + // + // Momentum Bar ... + bool isMomentumBarPattern = false; + if (checkMomentumPattern) + { + // + isMomentumBarPattern = + IsMomentumBar(bar, tmpDir) && + tmpDir == forDir; + } + + // + result = + isStarPattern || + isPinBarPattern || + isPiercingPattern || + isEngulfedPattern || + isMomentumBarPattern || + isSignalKeyBarPattern; + + // + return result; + } + + /** + * Detect Order Flow ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param orderFlow: XBoxZone, collection reference to holds Detected Order Flow ... + * @param orderFlowValidation: int, number of sequential Zones for Validate Order Flow ... + * @param containsOBs: bool, Specified to Use Order Blocks in Order Flow Detection ... + * @param containsFVGs: bool, Specified to Use Fair Value Gaps in Order Flow Detection ... + * @param containsSupportResistances: bool, Specified to Use Support and Resistances in Order Flow Detection ... + * @param zonesLoopback: int, Zone Detection Loopback ... + * @param zonesValidationLength: int, Zone Validation Length ... + * @param loopback: int, Max Allowed Loopback Bars for Collecting ... + * + * @return ( bool ) + */ + bool HasOrderFlow( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &orderFlow[], + int orderFlowValidation = 2, + bool containsOBs = false, + bool containsFVGs = true, + bool containsSupportResistances = false, + int zonesLoopback = 5, + int zonesValidationLength = 21, + int loopback = 100 // + ) + { + // + bool result = false; + + // + // Prepare ... + XClean(orderFlow); + CleanDirection(dir); + int maxRequiredZone = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + orderFlowValidation = NormalizeInt(orderFlowValidation, 1); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Collectiong Zones ... + XBoxZone tmp; + XBoxZone tmps[]; + XBoxZone _zones[]; + XBoxZone bullishZones[]; + XBoxZone bearishZones[]; + int bullishZonesCount = 0; + int bearishZonesCount = 0; + + // + // Order Blocks ... + if (containsOBs) + { + // + XClean(tmps); + CollectOBs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Fair Value Gaps ... + if (containsFVGs) + { + // + XClean(tmps); + CollectFVGs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Support and Resistances ... + if (containsSupportResistances) + { + // + XClean(tmps); + CollectZones(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Validate Zones ... + result = HasChild(_zones); + + // + // Extract Only Validated Zones ... + if (result) + { + // + ValidateBoxes( + _zones, + bar.Index() // Bars Length ... + ); + + // + UpdateToTime(_zones, bar.time); + RemoveBreakedZones(_zones, X_PRICE_CLOSE); + + // + result = HasChild(_zones); + } + + // + // Separate Zones Direction ... + if (result) + { + // + bullishZonesCount = ExtractByDirection(bullishZones, _zones, X_DIRECTION_BULLISH); + bearishZonesCount = ExtractByDirection(bearishZones, _zones, X_DIRECTION_BEARISH); + + // + result = IsValidSize(bullishZonesCount) || + IsValidSize(bearishZonesCount); + } + + // + // Looking for Sequences of Zones ... + if (result) + { + // + int idx = -1; + bool has = false; + XBoxZone bullOrderFlow[]; + XBoxZone bearOrderFlow[]; + + // + // Bullish OrderFlow ... + + // + // Sorting ... + Copy(bullishZones, bullOrderFlow); + Sort( + bullOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH, + orderFlowValidation + 1 // + ); + bool hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + if (hasBullishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bullOrderFlow, tmps); + XClean(bullOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetHighest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].lower < tmp.lower; + if (has) + { + AddIfNotExists(tmp, bullOrderFlow); + } + } + + // + hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + } + + // + // Bearish OrderFlow ... + + // + // Sorting ... + Copy(bearishZones, bearOrderFlow); + Sort( + bearOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BULLISH, + orderFlowValidation + 1 // + ); + bool hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + if (hasBearishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bearOrderFlow, tmps); + XClean(bearOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetLowest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].upper > tmp.upper; + if (has) + { + AddIfNotExists(tmp, bearOrderFlow); + } + } + + // + hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + } + + // + result = hasBullishOrderFlow || + hasBearishOrderFlow; + + // + // Validate Order Flows ... + if (result) + { + // + has = (hasBullishOrderFlow && !hasBearishOrderFlow) || + (hasBearishOrderFlow && !hasBullishOrderFlow); + + // + // When only Have One Direction ... + if (has) + { + // + if (hasBullishOrderFlow) + { + // + dir = X_DIRECTION_BULLISH; + Copy(bullOrderFlow, orderFlow); + } + else if (hasBearishOrderFlow) + { + // + dir = X_DIRECTION_BEARISH; + Copy(bearOrderFlow, orderFlow); + } + } + // + // When Two Direction Exists ... + else + { + // + // Retrieve Oldest Of Bullish / Bearish ... + int oldestBullIDX = GetOldest(bullOrderFlow); + int oldestBearIDX = GetOldest(bearOrderFlow); + result = IsValidIndex(oldestBullIDX) && + IsValidIndex(oldestBearIDX); + if (result) + { + // + dir = + bullOrderFlow[oldestBullIDX].from > bearOrderFlow[oldestBearIDX].from + ? X_DIRECTION_BULLISH + : bearOrderFlow[oldestBearIDX].from > bullOrderFlow[oldestBullIDX].from + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + if (result) + { + // + if (IsXBullish(dir)) + { + Copy(bullOrderFlow, orderFlow); + } + else if (IsXBearish(dir)) + { + Copy(bearOrderFlow, orderFlow); + } + } + } + } + + // + XClean(bullOrderFlow); + XClean(bearOrderFlow); + + // + result = HasChild(orderFlow) && + HasDirection(dir); + } + + // + // Validate Price ... + if (result) + { + // + int idx = -1; + if (IsXBullish(dir)) + { + // + idx = GetHighest(orderFlow); + result = IsValidIndex(idx) && + bar.low > orderFlow[idx].upper; + } + else + { + // + idx = GetLowest(orderFlow); + result = IsValidIndex(idx) && + bar.high < orderFlow[idx].lower; + } + } + + // + // Update To Time of Order Flow ... + if (result) + { + UpdateToTime(orderFlow, bar.time); + } + + // + // Cleanup ... + if (!result) + { + // + XClean(orderFlow); + CleanDirection(dir); + } + tmp.Clean(); + XClean(tmps); + XClean(_zones); + XClean(bullishZones); + XClean(bearishZones); + + // + return result; + } + + // + // FVG ... + + /** + * Check For FVG Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param fvg: XBoxZone, reference for Holding FVG ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup FVG ... + * + * @return ( bool ) + */ + bool HasFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvg, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + fvg.Clean(); + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is FVG or not ... + has = barAnalyser.IsFVG( + iBar, + fvg, + true // Force Bar Type ... + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = fvg.dir; + + // + break; + } + + // + // Check FVG Exists ... + result = fvg.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + fvg.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + // + // OB ... + + /** + * Check For OB Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param ob: XBoxZone, reference for Holding OB ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup OB ... + * + * @return ( bool ) + */ + bool HasOB( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &ob, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + ob.Clean(); + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is OB or not ... + has = barAnalyser.IsOB( + iBar, + ob, + true, // Force FVG Bar Type ... + true // Force OB First Two Bar InDirection ... + ); + if (!has) + { + // + ob.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = ob.dir; + + // + break; + } + + // + // Check OB Exists ... + result = ob.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + ob.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + // + // Complex ... + + /** + * Check Double Pinned Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Pattern Direction ... + * @param shadowApprovedMultiplier: double, Shadow Size Approve Multiplier ... + * @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ... + * @param forceDirection: bool, Apply Force Bar Type ... + * @param loopback: int, Max Allowed Detecting Loopback lenght ... + * + * @return ( bool ) + */ + bool IsDoublePinned( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false, + int loopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + shadowApprovedMultiplier = NormalizeDouble(shadowApprovedMultiplier, 2, 5); + minimumPinBarRangeMultiplier = NormalizeDouble(minimumPinBarRangeMultiplier, 2, 100); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Current Bar Must be a Pinned Bar ... + result = IsPinnedBar( + bar, + dir, + shadowApprovedMultiplier, + minimumPinBarRangeMultiplier, + forceDirection // + ); + if (!result) + { + // + CleanDirection(dir); + + // + return result; + } + + // + XOHCL iBar; + ENUM_X_DIRECTION iDir; + int start = bar.Index() + 1; + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + result = bar.BarAt(i, iBar); + result = result && IsPinnedBar( + iBar, + iDir, + shadowApprovedMultiplier, + minimumPinBarRangeMultiplier, + forceDirection // + ); + result = result && + iDir == dir; + if (result) + { + break; + } + } + + // + // Cleanup ... + if (!result) + { + CleanDirection(dir); + } + iBar.Clean(); + CleanDirection(iDir); + + // + return result; + } + + /** + * Check Double Engulfed Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Pattern Direction ... + * @param loopback: int, Max Allowed Detecting Loopback lenght ... + * + * @return ( bool ) + */ + bool IsDoubleEngulfed( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Current Bar Must be a Pinned Bar ... + result = IsEngulfedBar( + bar, + dir // + ); + if (!result) + { + // + CleanDirection(dir); + + // + return result; + } + + // + XOHCL iBar; + ENUM_X_DIRECTION iDir; + int start = bar.Index() + 1; + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + result = bar.BarAt(i, iBar); + result = result && IsEngulfedBar( + iBar, + iDir // + ); + result = result && + iDir == dir; + if (result) + { + break; + } + } + + // + // Cleanup ... + if (!result) + { + CleanDirection(dir); + } + iBar.Clean(); + CleanDirection(iDir); + + // + return result; + } + + /** + * Check Double Momentum Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Pattern Direction ... + * @param requiredBars: int, bar range for approve Momentum ... + * @param approvedMultiplier: double, a Multipler for approve Momentum ... + * @param loopback: int, Max Allowed Detecting Loopback lenght ... + * + * @return ( bool ) + */ + bool IsDoubleMomentum( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int requiredBars = 3, + double approvedMultiplier = 2, + int loopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + requiredBars = NormalizeInt(requiredBars, 3, 10); + approvedMultiplier = NormalizeDouble(approvedMultiplier, 2, 5); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Current Bar Must be a Pinned Bar ... + result = IsMomentumBar( + bar, + dir, + requiredBars, + approvedMultiplier // + ); + if (!result) + { + // + CleanDirection(dir); + + // + return result; + } + + // + XOHCL iBar; + ENUM_X_DIRECTION iDir; + int start = bar.Index() + 1; + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + result = bar.BarAt(i, iBar); + result = result && IsMomentumBar( + iBar, + iDir, + requiredBars, + approvedMultiplier // + ); + result = result && + iDir == dir; + if (result) + { + break; + } + } + + // + // Cleanup ... + if (!result) + { + CleanDirection(dir); + } + iBar.Clean(); + CleanDirection(iDir); + + // + return result; + } + + /** + * Check Has Double Patterns ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Specified Patterns ... + * @param barPatterns: XPatternAnalysis, reference to Provides Bar's Pattern Analysis ... + * @param pBarPatterns: XPatternAnalysis, reference to Provides Previous Bar's Pattern Analysis ... + * @param allowedPatterns: ENUM_X_BAR_PATTERN, collection to Provide Allowed Bar Patterns for Detection ... + * @param config: XPatternAnalysisConfig, Provides Patterns Detection Config ... + * @param loopback: int, Max Allowed Loopback for Detection ... + * @param forDir: ENUM_X_DIRECTION, Specified Patterns Detection Direction ... + * + * @return ( bool ) + */ + bool HasDoublePatterns( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XPatternAnalysis &barPatterns, + XPatternAnalysis &pBarPatterns, + ENUM_X_BAR_PATTERN &allowedPatterns[], + XPatternAnalysisConfig &config, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + // Prepare ... + barPatterns.Clean(); + CleanDirection(dir); + pBarPatterns.Clean(); + XPatternAnalysisConfig iConfig = config; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 2); + + // + // Validate ... + result = bar.IsValid() && + HasChild(allowedPatterns); + if (!result) + { + return result; + } + + // + // Prepare Config ... + iConfig.CleanPatterns(); + if (HasChild(allowedPatterns)) + { + // + for (int i = 0; i < ArraySize(allowedPatterns); i++) + { + iConfig.AddPattern(allowedPatterns[i]); + } + } + + // + // Detect Bar Patterns ... + result = AnalyseBarPatterns(bar, barPatterns, config); + if (!result) + { + // + CleanDirection(dir); + barPatterns.Clean(); + pBarPatterns.Clean(); + + // + return result; + } + + // + // Check Direction ... + int bullishCount = barPatterns.Count(X_DIRECTION_BULLISH); + int bearishCount = barPatterns.Count(X_DIRECTION_BEARISH); + dir = + bullishCount > bearishCount + ? X_DIRECTION_BULLISH + : bearishCount > bullishCount + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + + // + // Check for Dir ... + if (HasDirection(forDir)) + { + // + result = + result && + dir == forDir; + } + + // + // Looping Back ... + if (result) + { + // + XOHCL iBar; + ENUM_X_DIRECTION iDir; + int start = bar.Index() + 1; + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + pBarPatterns.Clean(); + result = bar.BarAt(i, iBar); + result = result && + AnalyseBarPatterns(iBar, pBarPatterns, iConfig); + if (!result) + { + continue; + } + + // + bullishCount = pBarPatterns.Count(X_DIRECTION_BULLISH); + bearishCount = pBarPatterns.Count(X_DIRECTION_BEARISH); + iDir = + bullishCount > bearishCount + ? X_DIRECTION_BULLISH + : bearishCount > bullishCount + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(iDir); + result = result && + dir == iDir; + if (result) + { + break; + } + } + + // + iBar.Clean(); + CleanDirection(iDir); + } + + // + // Cleanup ... + if (!result) + { + // + CleanDirection(dir); + barPatterns.Clean(); + pBarPatterns.Clean(); + } + iConfig.Clean(); + + // + return result; + } + + /** + * Count Same Bars ... + * + * @param bar: XOHCL, Specified Bar ... + * @param sameBars: XOHCL, collection reference to holds same Bars ... + * @param dir: ENUM_X_DIRECTION, refrence to Founded Bars Direction holding ... + * @param forDir: ENUM_X_DIRECTION, Specified Looking Bar ... + * + * @return ( int ) + */ + int CountSameBars( + XOHCL &bar, + XOHCL &sameBars[], + ENUM_X_DIRECTION &dir, + ENUM_X_DIRECTION forDir // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(sameBars); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL tmpBar; + ENUM_X_DIRECTION tmpDir = forDir; + int idx = bar.Index(); + while (has) + { + // + idx++; + tmpBar.Clean(); + has = bar.BarAt(idx, tmpBar); + if (has && !HasDirection(tmpDir)) + { + tmpDir = tmpBar.GetDirection(); + } + has = has && + tmpBar.GetDirection() == tmpDir; + if (!has) + { + break; + } + + // + AddIfNotExists(tmpBar, sameBars); + } + + // + result = ArraySize(sameBars); + if (IsValidSize(result)) + { + dir = tmpDir; + } + + // + // Cleanup ... + tmpBar.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; + } + + /** + * Check Specified Bar Has Support or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param support: XOHCL, Supported Bar ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + 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; + } + + /** + * Check Specified Bar Has Resistance or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param resistence: XOHCL, Resistanced Bar ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + 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; + } + + /** + * Check Specified Bar Has Support or Resistance and Extract them ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param support: XBoxZone, reference to holds Detected Support ... + * @param resistance: XBoxZone, reference to holds Detected Resistance ... + * @param validationLength: int, Specified Validation Length ... + * @param loopback: int, Max Allowed Loopback Bars for Detection ... + * + * @return ( bool ) + */ + bool HasSupportResistance( + XOHCL &bar, + XBoxZone &support, + XBoxZone &resistance, + int validationLength = 7, + int loopback = 100 // + ) + { + // + bool result = false; + + // + // Prepare ... + support.Clean(); + resistance.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iZBar; + + // + // Support ... + iZBar.Clean(); + bool hasSupport = HasSupport( + bar, + iZBar, + validationLength, + loopback // + ); + if (hasSupport) + { + // + hasSupport = ToSupportBox( + iZBar, + support, + bar.time // + ); + } + + // + // Resistance ... + iZBar.Clean(); + bool hasResistance = HasResistance( + bar, + iZBar, + validationLength, + loopback // + ); + if (hasResistance) + { + // + hasResistance = ToResistanceBox( + iZBar, + resistance, + bar.time // + ); + } + + // + // Summarize Result ... + result = hasSupport || + hasResistance; + + // + // Cleanup ... + iZBar.Clean(); + + // + return result; + } + + // + // Analysers ... + + /** + * Analyse Specified Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param analysis: XPatternAnalysis, reference to holds Analysis result ... + * @param config: XPatternAnalysisConfig, reference to Provides Detector Configs ... + * + * @return ( bool ) + */ + bool AnalyseBarPatterns( + XOHCL &bar, + XPatternAnalysis &analysis, + XPatternAnalysisConfig &config // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + analysis.bar = bar; + analysis.time = TimeCurrent(); + + // + XOHCL iSwing; + XBoxZone iZone; + ENUM_X_DIRECTION iDir; + ENUM_X_BAR_PATTERN iPattern; + + // + bool has; + bool isBullish; + bool isBearish; + + // + bool canDetect; + bool canDetectBullish; + bool canDetectBearish; + + // + // Bars Detectors ... + + // + // XPV High Low Detection ... + canDetect = config.CanDetect(X_BAR_PATTERN_HIGH) || + config.CanDetect(X_BAR_PATTERN_LOW); + if (canDetect) + { + // + has = IsPV( + bar, + iDir, + config.pvValidationLength, + config.peakPriceType, + config.valePriceType // + ); + + // + canDetectBullish = config.CanDetect(X_BAR_PATTERN_LOW); + canDetectBearish = config.CanDetect(X_BAR_PATTERN_HIGH); + + // + isBullish = + has && + IsXBullish(iDir) && + canDetectBullish; + + // + isBearish = + has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + iPattern = + isBearish + ? X_BAR_PATTERN_HIGH + : X_BAR_PATTERN_LOW; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Momentum ... + iPattern = X_BAR_PATTERN_MOMENTUM; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsMomentumBar( + bar, + iDir, + config.momentumBarValidationLength, + config.momentumBarApprovedMultiplier // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Engulfed ... + iPattern = X_BAR_PATTERN_ENGULFED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsEngulfedBar( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // TrueGap ... + iPattern = X_BAR_PATTERN_TRUE_GAPED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsTrueGapedBar( + bar, + iDir, + config.trueGapApprovedStrength // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Pinned ... + iPattern = X_BAR_PATTERN_PINNED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsPinnedBar( + bar, + iDir, + config.pinBarShadowApprovedMultiplier, + config.pinBarRangeMultiplier, + config.pinBarForceDirection // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Pattern Detectors ... + + // + // Star ... + iPattern = X_BAR_PATTERN_STAR; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsStarPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Piercing ... + iPattern = X_BAR_PATTERN_PIERCING; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsPiercingPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Rising ... + iPattern = X_BAR_PATTERN_RISING; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsRisingPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Flag ... + iPattern = X_BAR_PATTERN_FLAG; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsFlagPattern( + bar, + iDir, + iSwing, + config.flagPatternPullbackLength // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + + // + analysis.flagSwing = iSwing; + } + } + + // + // SignalKey ... + iPattern = X_BAR_PATTERN_SIGNALKEY; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsSignalKeyBarPattern( + bar, + iDir, + config.pinBarShadowApprovedMultiplier, + config.pinBarRangeMultiplier, + config.pinBarForceDirection // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Zone Detectors ... + + // + // OB ... + iPattern = X_BAR_PATTERN_OB; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = barAnalyser.IsOB( + bar, + iZone, + config.fvgForceType, + config.obForceTwoBar // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + iZone.IsBullish() && + canDetectBullish; + isBearish = has && + iZone.IsBearish() && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.ob = iZone; + } + } + + // + // FVG ... + iPattern = X_BAR_PATTERN_FVG; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = barAnalyser.IsFVG( + bar, + iZone, + config.fvgForceType // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + iZone.IsBullish() && + canDetectBullish; + isBearish = has && + iZone.IsBearish() && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.fvg = iZone; + } + } + + // + // Support ... + iPattern = X_BAR_PATTERN_SUPPORT; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = HasSupport( + bar, + iSwing, + config.supportAndResistanceValidationLength, + config.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox( + iSwing, + iZone, + bar.time, + config.supportAndResistanceValidationLength // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.support = iZone; + } + } + } + + // + // Resistance ... + iPattern = X_BAR_PATTERN_RESISTANCE; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = HasResistance( + bar, + iSwing, + config.supportAndResistanceValidationLength, + config.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox( + iSwing, + iZone, + bar.time, + config.supportAndResistanceValidationLength // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.resistance = iZone; + } + } + } + + // + // Validate Analysis ... + result = analysis.IsValid(); + + // + // Cleanup Resources ... + iZone.Clean(); + iSwing.Clean(); + CleanDirection(iDir); + + // + return result; + } + + /** + * Collect Required Order Blocks ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dest: XBoxZone, collection reference to holds detected zones ... + * @param zonesLoopback: int, zones detection loopback ... + * @param maxRequiredZone: int, number of required zones ... + * @param loopback: int, max allowed loopback lenght for zone Detection ... + * + * @return ( int ) + */ + int CollectOBs( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + ENUM_X_DIRECTION iDir; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + has = bar.BarAt(i, iBar); + has = has && + HasOB(iBar, iDir, iBox, zonesLoopback); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + return result; + } + + /** + * Collect Required Fair Value Gaps ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dest: XBoxZone, collection reference to holds detected zones ... + * @param zonesLoopback: int, zones detection loopback ... + * @param maxRequiredZone: int, number of required zones ... + * @param loopback: int, max allowed loopback lenght for zone Detection ... + * + * @return ( int ) + */ + int CollectFVGs( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + ENUM_X_DIRECTION iDir; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + has = bar.BarAt(i, iBar); + has = has && + HasFVG(iBar, iDir, iBox, zonesLoopback); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + return result; + } + + /** + * Collect Required Support and Resistance Zones ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dest: XBoxZone, collection reference to holds detected zones ... + * @param zonesLoopback: int, zones detection loopback ... + * @param zonesValidationLength: int, zones validation length ... + * @param maxRequiredZone: int, number of required zones ... + * @param loopback: int, max allowed loopback lenght for zone Detection ... + * + * @return ( int ) + */ + int CollectZones( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int zonesValidationLength = 21, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + XOHCL iZoneBar; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iZoneBar.Clean(); + + // + has = bar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Support ... + has = HasSupport(iBar, iZoneBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToSupportBox(iZoneBar, iBox, bar.time, zonesValidationLength); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + } + + // + // Resistance ... + has = HasResistance(iBar, iZoneBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToResistanceBox(iZoneBar, iBox, bar.time, zonesValidationLength); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iZoneBar.Clean(); + + // + return result; + } + + /** + * Detect and Collect Required Zones ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zones: XBoxZone, collection reference to holds detected zones ... + * @param validateZones: bool, Specified to Detect only Valid Zones ... + * @param containsOBs: bool, Flag to use Order Block Zones ... + * @param containsFVGs: bool, Flag to use Fair Value Gap Zones ... + * @param containsSupports: bool, Flag to use Support Zones ... + * @param containsResistancess: bool, Flag to use Resistance Zones ... + * @param forDir: ENUM_X_DIRECTION, Specified Zones Direction for Detecting ... + * @param sortby: ENUM_X_SORT_BY, Specified Zones Sorting Factor ... + * @param sortDir: ENUM_X_DIRECTION, Specified Zones Sorting Direction ... + * @param zonesRangeValidationFactor: double, Specified Zones Range Validation in Points ... + * @param zonesLoopback: int, loop back for Zones Detection ... + * @param zonesValidationLength: int, zones Validation Length ... + * @param count: int, number of required Zones ... + * @param loopback: int, max allowed looping back lenght for detection ... + * + * @return ( int ) + */ + int DetectZones( + XOHCL &bar, + XBoxZone &zones[], + bool validateZones = true, + bool containsOBs = true, + bool containsFVGs = true, + bool containsSupports = true, + bool containsResistancess = true, + int loopback = 500, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH, + double zonesRangeValidationFactor = 10, + int zonesLoopback = 5, + int zonesValidationLength = 5, + int count = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(zones); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + zonesLoopback = NormalizeInt(zonesLoopback, 2); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + bool has = bar.IsValid() && + IsXValid(sortDir) && + IsXValid(sortBy) && + (containsOBs || containsFVGs || containsSupports || containsResistancess); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone tmpZone; + ENUM_X_DIRECTION tmpDir; + int idx = bar.Index(); + while (idx < bar.Index() + loopback) + { + // + idx++; + + // + iBar.Clean(); + tmpBar.Clean(); + tmpZone.Clean(); + tmpPivot.Clean(); + + // + has = bar.BarAt(idx, iBar); + if (!has) + { + continue; + } + + // + // Collecting Zones ... + + // + // Support ... + if (containsSupports) + { + // + if (!HasDirection(forDir) || IsXBullish(forDir)) + { + // + has = HasSupport(iBar, tmpBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToBox(tmpBar, tmpZone, X_DIRECTION_BULLISH, X_BAR_PATTERN_SUPPORT); + if (has) + { + AddIfNotExists(tmpZone, zones); + } + } + } + } + + // + // Resistance ... + if (containsResistancess) + { + // + if (!HasDirection(forDir) || IsXBearish(forDir)) + { + // + has = HasResistance(iBar, tmpBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToBox(tmpBar, tmpZone, X_DIRECTION_BEARISH, X_BAR_PATTERN_RESISTANCE); + if (has) + { + AddIfNotExists(tmpZone, zones); + } + } + } + } + + // + // Order Block ... + if (containsOBs) + { + // + has = HasOB(iBar, tmpDir, tmpZone, zonesLoopback); + if (has && (!HasDirection(forDir) || tmpDir == forDir)) + { + AddIfNotExists(tmpZone, zones); + } + } + + // + // Fair Value Gaps ... + if (containsFVGs) + { + // + has = HasFVG(iBar, tmpDir, tmpZone, zonesLoopback); + if (has && (!HasDirection(forDir) || tmpDir == forDir)) + { + AddIfNotExists(tmpZone, zones); + } + } + } + + // + // Validate Zones Exists ... + result = ArraySize(zones); + has = IsValidSize(result); + if (!has) + { + return result; + } + + // + // Update Zones Time ... + UpdateToTime(zones, bar.time); + + // + // Validate Zones ... + if (validateZones) + { + // + // Apply Zones Validation Here ... + RemoveBreakedZones(zones, true); + } + + // + // Validate Zones Range ... + if (zonesRangeValidationFactor > 0) + { + // + double points = GetPoints(bar.symbol); + double minAllowedRange = points * zonesRangeValidationFactor; + ValidateZonesRange(zones, minAllowedRange); + } + + // + // Apply Sorting ... + Sort(zones, sortBy, sortDir); + + // + // Validate Zones Count ... + if (count > 0) + { + CleanupArray(zones, count); + } + + // + result = ArraySize(zones); + + // + // Cleanup ... + iBar.Clean(); + tmpBar.Clean(); + tmpZone.Clean(); + tmpPivot.Clean(); + + // + return result; + } + + /** + * Filter Zones ... + * + * @param bar: XOHCL, reference to Specified Filtering Bar ... + * @param source: XBoxZone, reference collection to hold's filtered zones ... + * @param filterDir: ENUM_X_DIRECTION, specified Filter Direction ... + * @param priceType: ENUM_X_PRICE, Specified Bar's Price type to Use for Filtering Zones ... + * @param forDir: ENUM_X_DIRECTION, Specified Zone's Direction to Handle Filtering ... + * + * @return ( int ) + */ + int FilterZones( + XOHCL &bar, + XBoxZone &source[], + ENUM_X_DIRECTION filterDir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XBoxZone tmp[]; + Copy( + source, + tmp // + ); + XClean(source); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(tmp) && + IsXValid(priceType) && + HasDirection(filterDir); + if (!has) + { + // + XClean(tmp); + return result; + } + + // + XBoxZone iBox; + double price = bar.GetPrice(priceType); + bool isBullish = IsXBullish(filterDir); + while (HasChild(tmp)) + { + // + iBox = tmp[0]; + ArrayRemove(tmp, 0, 1); + + // + has = + // + // Direction Pass ... + (!HasDirection(forDir) + ? true + : forDir == iBox.dir) + // + && + // + // Price Pass ... + (isBullish + ? price > iBox.lower + : price < iBox.upper); + if (has) + { + AddIfNotExists(iBox, source); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(source); + + // + // Cleanup ... + XClean(tmp); + iBox.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Tools / Actions ... + + /** + * Check Zones and Manage them ... + * + * @param forBar: XOHCL, reference to Specified Bar ... + * @param _zones: XBoxZone, reference to Specified Zone Collection ... + * @param sortBy: X_SORT_BY_DATE, Sort Zones by ... + * @param sortDir: ENUM_X_DIRECTION, Sort Zones in Direction ... + * @param maxAllowed: int, Specified Max Allowed Zones ... + */ + void CheckZones( + XOHCL &forBar, + XBoxZone &_zones[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH, + int maxAllowed = 50 // + ) + { + // + // Normalize ... + maxAllowed = NormalizeInt(maxAllowed, 0); + + // + // Validate ... + bool has = forBar.IsValid() && + HasChild(_zones); + if (!has) + { + return; + } + + // + // Looping Through Zones ... + int count = ArraySize(_zones); + for (int i = 0; i < count; i++) + { + // + // Check Break ... + has = IsXValid(_zones[i].breakAt); + if (has) + { + continue; + } + + // + _zones[i].to = forBar.time; + + // + // Check for Test ... + has = IsTested( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].tests // + ); + } + + // + // Check for Inside ... + has = IsInside( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].insides // + ); + } + + // + // Check for Break ... + has = IsBreaked( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].breaks // + ); + } + + // + // Check for Act ... + has = IsActed( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].acteds // + ); + } + + // + // Check for FakeBreakes ... + has = IsFakeBreaked( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].fakeBreaks // + ); + } + + // + // Check for Valid Breakes ... + has = IsValidBreaked( + forBar, + _zones[i] // + ); + if (has) + { + _zones[i].breakAt = forBar.time; + } + } + + // + // Apply Sort and Cleanup ... + Sort( + _zones, + sortBy, + sortDir, + maxAllowed // + ); + } + + // + // Private ... + private: + // + // Props ... + XCBarAnalyser *barAnalyser; + + // + // 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/14041018/Classes/x-saherelm.x-md5.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-md5.class.mq5 new file mode 100644 index 0000000..6bd1c4e --- /dev/null +++ b/BKPS/14041018/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/14041018/Classes/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..0df9b0c --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,2790 @@ +/////////////////////////////////////////////////////// +// +// 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-pivot.analysis.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +// Implementations ... +class XCPOIDrawer : public XCBase +{ + // + public: + // + // Props ... + + // + XPOIStyle defaultBullishStyle; + XPOIStyle defaultBearishStyle; + + // + XPOIStyle boxBullishStyle; + XPOIStyle boxBearishStyle; + + // + CArrayObj drawnObjects; + + // + // Constructor ... + XCPOIDrawer() + { + // + Default(); + } + + // + // Deconstructor ... + ~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; + } + + // + // Virtuals ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrLime; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrRed; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + } + + // + // Drawers ... + + /** + * Draw Specified Bar ... + * + * @param bar: XOHCL, refrence to Specified Bar ... + * @param object: XCOHCLObject, pointer reference for Drawn Object ... + * @param to: datetime, Specified To Time ... + * + * @return ( bool ) + */ + bool DrawBar( + XOHCL &bar, + XCOHCLObject *&object, + datetime to = NULL // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + ulong chartId = ChartIdentification(); + int window = SubWindowIdentification(); + to = IsSpecifiedValid(to) + ? to + : ((datetime)((int)bar.time) + (PeriodSeconds(bar.period) - 1)); + object = new XCOHCLObject(); + result = object.Create( + chartId, + window, + bar, + to, + prefix // + ); + if (result) + { + // + ApplyBarStyle( + object, + bar // + ); + } + + // + return result; + } + + /** + * Draw Bar Arrow Object ... + * + * @param bar: XOHCL instance Reference ... + * @param object: XCBarArrowObject, pointer reference for Drawn Object ... + * @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 DrawBarArrow( + 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 ignoreBarTag = true, + int threshold = 5 // + ) + { + // + 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(); + + // + prefix = + (IsValid(prefix) + ? prefix + "_" + : prefix) + + (IsSpecifiedValid(name) + ? name + : "") + + (ignoreBarTag ? "" : ToMD5(barTag)); + + // + object = new XCBarArrowObject(); + result = object + .CreateByBar( + chartID, + prefix, + window, + arrow, + bar, + priceType, + threshold // + ); + if (result) + { + // + object.ArrowColor(clr); + object.ArrowWidth(width); + object.ArrowAnchor(anchor); + } + + // + return result; + } + + /** + * Dar Specified Pivot ... + * + * @param pivot: XPivot, Specified Pivot ... + * @param object: XCBarArrowObject, pointer reference for Drawn Object ... + * @param peakArrow: int, Specified Arrow Code for Peak Pivots ... + * @param valeArrow: int, Specified Arrow Code for Vale Pivots ... + * @param threshold: int, distance between price and arrow in Point ... + * + * @return ( bool ) + */ + bool DrawPivot( + XPivot &pivot, + XCBarArrowObject *&object, + int peakArrow = 159, + int valeArrow = 159, + int threshold = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Normalize ... + threshold = NormalizeInt(threshold, 5); + peakArrow = NormalizeInt(peakArrow, 159); + valeArrow = NormalizeInt(valeArrow, 159); + + // + // Validate ... + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + // Get Pivot's Bar ... + XOHCL bar; + result = pivot.GetBar(bar); + if (!result) + { + return result; + } + + // + int arrow = pivot.IsPeak() + ? peakArrow + : valeArrow; + string name = pivot.GetObjectID(); + ENUM_X_PRICE type = pivot.IsPeak() + ? X_PRICE_HIGH + : X_PRICE_LOW; + XPOIStyle style = pivot.IsPeak() + ? defaultBearishStyle + : defaultBullishStyle; + ENUM_ARROW_ANCHOR anchor = pivot.IsPeak() + ? ANCHOR_BOTTOM + : ANCHOR_TOP; + object = new XCBarArrowObject(); + result = object.CreateByBar( + ChartIdentification(), + name, + SubWindowIdentification(), + arrow, + bar, + type, + threshold // + ); + if (result) + { + // + // Apply Styles ... + object.ArrowAnchor(anchor); + ApplyBarArrowStyle( + object, + style // + ); + } + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; + } + + /** + * Draw Specified Pivot Collection ... + * + * @param pivots: XPivot, reference Collection to Draw ... + * @param draws: CArrayObj, pointer reference to Hold Drawn Objects ... + * @param peakArrow: int, Specified Arrow Code for Peak Pivots ... + * @param valeArrow: int, Specified Arrow Code for Vale Pivots ... + * @param threshold: int, distance between price and arrow in Point ... + * + * @return ( int ) + */ + int DrawPivots( + XPivot &pivots[], + CArrayObj *&draws, + int peakArrow = 159, + int valeArrow = 159, + int threshold = 5 // + ) + { + // + int result = 0; + + // + // Prepare ... + if (draws == NULL) + { + draws = new CArrayObj(); + } + draws.Clear(); + + // + // Validate ... + if (!HasChild(pivots)) + { + return result; + } + + // + bool has = false; + XCBarArrowObject *iObj; + int count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + // Draw Indexed Pivot ... + has = DrawPivot( + pivots[i], + iObj, + peakArrow, + valeArrow, + threshold // + ); + + // + if (has) + { + draws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + result = draws.Total(); + + // + return result; + } + + /** + * Draw Specified Box ... + * + * @param object: XCBoxObject, pointer reference for Drawn Object ... + * @param name: Box Name ... + * @param upper: double, Box Upper ... + * @param lower: double, Box Lower ... + * @param from: datetime, From Time ... + * @param to: datetime, To Time ... + * @param at: datetime, Specified At Time ... + * + * @return ( bool ) + */ + bool DrawBox( + XCBoxObject *&object, + string name, + double upper, + double lower, + datetime from, + datetime to, + datetime at // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Normalize ... + to = NormalizeTime(to); + from = NormalizeTime(from); + + // + // Validate ... + result = + upper > 0 && + lower > 0 && + to > from && + IsSpecifiedValid(to) && + IsSpecifiedValid(name) && + IsSpecifiedValid(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 // + ); + + // + return result; + } + + /** + * Draw Specific Box ... + * + * @param box: XBoxZone, Specified Box ... + * @param object: XCBarArrowObject, pointer reference for Drawn Object ... + * @param ignoreAt: bool, Ignore Box at or not ... + * + * @return ( bool ) + */ + bool DrawBox( + XBoxZone &box, + XCBoxObject *&object, + bool ignoreAt = true, + string name = NULL // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Validate ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + datetime at = box.at; + if (ignoreAt) + { + at = NULL; + } + + // + name = IsSpecifiedValid(name) + ? name + : box.GetTag(); + result = DrawBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + at // + ); + if (result) + { + // + // Apply Style ... + XPOIStyle style; + GetBoxStyle( + style, + box.dir // + ); + + // + ApplyBoxStyle( + object, + style // + ); + + // + style.Clean(); + } + + // + return result; + } + + /** + * Draw a Collection of Boxes ... + * + * @param boxes: reference collection to Provide Boxes ... + * @param objects: reference pointer to holds drawn Objects ... + * @param ignoreAt: bool, ignore Box At Drawn ... + * + * @return ( int ) + */ + int DrawBoxes( + XBoxZone &boxes[], + CArrayObj *&objects, + bool useTypeName = true, + bool ignoreAt = true // + ) + { + // + int result = 0; + + // + // Prepare ... + objects = new CArrayObj(); + + // + // Validate ... + if (!HasChild(boxes)) + { + return result; + } + + // + bool has = false; + XCBoxObject *iObj; + string name = NULL; + int count = ArraySize(boxes); + for (int i = 0; i < count; i++) + { + // + if (useTypeName) + { + name = boxes[i].type; + } + + // + has = DrawBox( + boxes[i], + iObj, + ignoreAt, + name // + ); + if (has) + { + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + result = objects.Total(); + + // + return result; + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal, Specified Signal ... + * @param object: XCSignalObject, pointer reference for Drawn Object ... + * @param length: int, Signal Length ... + */ + 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 Specified Trend Line ... + * + * @param fromPrice: double, from Price ... + * @param fromTime: datetime, from Time ... + * @param toPrice: double, to Price ... + * @param toTime: datetime, to Time ... + * @param object: CChartObjectTrend, pointer reference for Drawn Object ... + * @param name: Object Name ... + * @param rayRight: bool, ray to Right ... + * @param rayLeft: boo, ray to Left ... + * + * @return ( bool ) + */ + bool DrawTrendLine( + double fromPrice, + datetime fromTime, + double toPrice, + datetime toTime, + CChartObjectTrend *&object, + string name, + bool rayRight = false, + bool rayLeft = false // + ) + { + // + bool result = false; + + // + // Prepare ... + object = new CChartObjectTrend(); + + // + // Validate ... + result = + toPrice > 0 && + fromPrice > 0 && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime) && + toTime > fromTime; + if (!result) + { + return result; + } + + // + // Create Object ... + result = object.Create( + ChartIdentification(), + name, + SubWindowIdentification(), + fromTime, + fromPrice, + toTime, + toPrice // + ); + if (result) + { + // + ENUM_X_DIRECTION dir = + fromPrice < toPrice + ? X_DIRECTION_BULLISH + : fromPrice > toPrice + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + ApplyTrendLineStyle( + object, + dir // + ); + + // + object.RayLeft(rayLeft); + object.RayRight(rayRight); + } + + // + return result; + } + + /** + * Draw Trend Line based on Swings Points ... + * + * @param swings: XOHCL, Specified Swings ... + * @param dir: ENUM_X_DIRECTION, Specified Trend Direction ... + * @param object: CChartObjectTrend, pointer reference for Drawn Object ... + * @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; + + // + // Prepare ... + object = NULL; + + // + int count = ArraySize(swings); + result = HasChild(swings) && + count >= 2 && + HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isBullish = IsSpecifiedBullish(dir); + + // + XOHCL _swings[]; + Copy( + swings, + _swings // + ); + SortBar( + _swings, + X_SORT_BY_DATE, + X_DIRECTION_BULLISH // + ); + + // + 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); + RemoveObjects("_Trend_", chartId, subWindow); + + // + object = new CChartObjectTrend(); + result = object.Create( + chartId, + name, + subWindow, + time1, + price1, + time2, + price2 // + ); + if (result) + { + // + ApplyTrendLineStyle( + object, + dir // + ); + + // + object.RayLeft(rayLeft); + object.RayRight(rayRight); + } + + // + SpecifiedClean(_swings); + + // + return result; + } + + // + // Stylers ... + + /** + * Get Specified Style for Specified Direction ... + * + * @param style: XPOIStyle, reference to hold result ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void GetStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + // Prepare ... + style.Clean(); + + // + // Validate ... + if (!HasDirection(forDir)) + { + return; + } + + // + if (IsSpecifiedBullish(forDir)) + { + style = defaultBullishStyle; + } + else + { + style = defaultBearishStyle; + } + } + + /** + * Get Specified Box Style for Specified Direction ... + * + * @param style: XPOIStyle, reference to hold result ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void GetBoxStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + // Prepare ... + style.Clean(); + + // + // Validate ... + if (!HasDirection(forDir)) + { + return; + } + + // + if (IsSpecifiedBullish(forDir)) + { + style = boxBullishStyle; + } + else + { + style = boxBearishStyle; + } + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: XCBoxObject, pointer reference of Object ... + * @param bar: XOHCL, Specified Bar ... + * @param fill: boolean, Fill Bar's Body or not ... + */ + void ApplyBarStyle( + XCOHCLObject *&object, + XOHCL &bar, + bool fill = false // + ) + { + // + // Validate ... + bool has = bar.IsValid() && + object != NULL; + if (!has) + { + return; + } + + // + XPOIStyle style; + GetStyle( + style, + bar.GetDirection() // + ); + + // + object.BarSpes( + style.width, + style.clr, + style.style, + fill // + ); + + // + style.Clean(); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: XCBoxObject, pointer reference of Object ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyBoxStyle( + XCBoxObject *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.BoxFill(style.fill); + object.BoxColor(style.clr); + object.BoxWidth(style.width); + object.BoxStyle(style.style); + } + + /** + * Apply Specified Style to a Collection on Drawn Boxes ... + * + * @param objects: pointer reference of Objects ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyBoxesStyle( + CArrayObj *&objects, + XPOIStyle &style // + ) + { + // + // Validate ... + if (objects == NULL || objects.Total() <= 0) + { + return; + } + + // + for (int i = 0; i < objects.Total(); i++) + { + // + XCBoxObject *iObj = ((XCBoxObject *)objects.At(i)); + ApplyBoxStyle( + iObj, + style // + ); + ZeroMemory(iObj); + } + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: XCBarArrowObject, pointer reference of Object ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyBarArrowStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObjectVLine, pointer reference of Object ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyLineStyle( + CChartObjectVLine *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.Color(style.clr); + object.Style(style.style); + object.Width(style.width); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObjectVLine, pointer reference of Object ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void ApplyLineStyle( + CChartObjectVLine *&object, + ENUM_X_DIRECTION forDir // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + has = HasDirection(forDir); + if (!has) + { + return; + } + + // + XPOIStyle style; + GetStyle(style, forDir); + + // + object.Color(style.clr); + object.Style(style.style); + object.Width(style.width); + + // + style.Clean(); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObjectHLine, pointer reference of Object ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyLineStyle( + CChartObjectHLine *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.Color(style.clr); + object.Style(style.style); + object.Width(style.width); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObjectHLine, pointer reference of Object ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void ApplyLineStyle( + CChartObjectHLine *&object, + ENUM_X_DIRECTION forDir // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + has = HasDirection(forDir); + if (!has) + { + return; + } + + // + XPOIStyle style; + GetStyle(style, forDir); + + // + object.Color(style.clr); + object.Style(style.style); + object.Width(style.width); + + // + style.Clean(); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObjectTrend, pointer reference of Object ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void ApplyTrendLineStyle( + CChartObjectTrend *&object, + ENUM_X_DIRECTION forDir // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + if (!HasDirection(forDir)) + { + return; + } + + // + XPOIStyle style; + GetStyle(style, forDir); + + // + object.Color(style.clr); + object.Style(style.style); + object.Width(style.width); + + // + style.Clean(); + } + + // + // SPecial Draws Functions ... + + /** + * Draw Specified Pattern Pivot ... + * + * @param _pivot: XPivot, reference to Specified Pivot ... + * @param config: XPOIDrawConfig, Darwing Configuration ... + * @param thresholdMultiplier: int, pivot point threshold ... + */ + void DrawPivot( + XPivot &_pivot, + XPOIDrawConfig &config, + int thresholdMultiplier = 0 // + ) + { + // + // Normalize ... + thresholdMultiplier = NormalizeInt(thresholdMultiplier, 1); + + // + int arrowThreshold = config.arrowsThreshold * thresholdMultiplier; + arrowThreshold = NormalizeInt(arrowThreshold, 1); + + // + // Validate ... + bool has = _pivot.IsValid(); + if (!has) + { + return; + } + + // + XOHCL _bar; + has = _pivot.GetBar(_bar); + if (!has) + { + // + _bar.Clean(); + return; + } + + // + XCBarArrowObject *iObj; + has = DrawBarArrow( + _bar, + iObj, + _pivot.IsPeak() + ? config.arrowsPeakPriceType + : config.arrowsValePriceType, + _pivot.IsBullish() + ? config.bullishArrow + : config.bearishArrow, + _pivot.IsBullish() + ? config.bullishColor + : config.bearishColor, + config.arrowsWidth, + _pivot.IsBullish() + ? ANCHOR_TOP + : ANCHOR_BOTTOM, + _pivot.prefix + "_Pivot_" + ToXString(TimeToSeconds(_pivot.time)), + true, // Ignore Bar Tag ... + arrowThreshold // Threshold ... + ); + if (has) + { + drawnObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + /** + * Draw Specified Pattern Zone ... + * + * @param _zone: XBozxZone, reference to Specified Zone ... + * @param config: XPOIDrawConfig, Darwing Configuration ... + */ + void DrawZone( + XBoxZone &_zone, + XPOIDrawConfig &config // + ) + { + // + // Validate ... + bool has = _zone.IsValid(); + if (!has) + { + return; + } + + // + XCBoxObject *iObj; + has = DrawBox( + _zone, + iObj, + config.ignoreZonesAt, + _zone.type + "_Zone_" + ToXString(TimeToSeconds(_zone.from)) // + ); + if (has) + { + // + XPOIStyle iStyle; + GetBoxStyle( + iStyle, + _zone.dir // + ); + + // + iStyle.clr = + _zone.IsBullish() + ? config.bullishColor + : config.bearishColor; + iStyle.width = config.zonesWidth; + iStyle.style = config.zonesStyle; + + // + ApplyBoxStyle( + iObj, + iStyle // + ); + + // + drawnObjects.Add(iObj); + + // + iStyle.Clean(); + } + + // + ZeroMemory(iObj); + } + + /** + * Draw Specified Zones ... + * + * @param _zone: XBozxZone, reference to Collection Specified Zone ... + * @param config: XPOIDrawConfig, Darwing Configuration ... + */ + void DrawZones( + XBoxZone &_zones[], + XPOIDrawConfig &config // + ) + { + // + // Validate ... + bool has = HasChild(_zones); + if (!has) + { + return; + } + + // + for (int i = 0; i < ArraySize(_zones); i++) + { + // + DrawZone( + _zones[i], + config // + ); + } + } + + /** + * Draw Pivots ... + * + * @param pivots: XPivot, collection reference to Draw ... + * @param config: XPOIDrawConfig, reference to Specified Draw Style ... + */ + void DrawPivots( + XPivot &pivots[], + XPOIDrawConfig &config // + ) + { + // + // Validate ... + bool has = HasChild(pivots); + if (!has) + { + return; + } + + // + XPivot tmps[]; + int count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XClean(tmps); + int sameCounts = ExtractSameTimePivots(pivots[i], tmps, pivots); + has = IsValidSize(sameCounts); + if (has) + { + // + for (int j = 0; j < sameCounts; j++) + { + DrawPivot(tmps[j], config, j + 1); + } + } + } + + // + // Cleanup ... + XClean(tmps); + } + + void DrawTrendLine( + string name, + double fromPrice, + datetime fromTime, + double toPrice, + datetime toTime, + XPOIDrawConfig &config, + color clr = CLR_NONE // + ) + { + // + // Validate ... + bool has = + IsXValid(name) && + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + fromTime < toTime; + if (!has) + { + return; + } + + // + ENUM_X_DIRECTION trendDir = + fromPrice > toPrice + ? X_DIRECTION_BEARISH + : fromPrice < toPrice + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + color clrTrend = + (clr != CLR_NONE) + ? clr + : IsXBullish(trendDir) + ? config.bullishColor + : config.bearishColor; + + // + CChartObjectTrend *object; + has = DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + object, + name, + config.trendRayRight, + config.trendRayLeft // + ); + if (has) + { + // + // Apply Style ... + object.Color(clrTrend); + object.Width(config.trendWidth); + object.Style(config.trendStyle); + + // + // Save Object ... + drawnObjects.Add(object); + } + + // + ZeroMemory(object); + } + + void DrawTrendLine( + XTrend &trend, + XPOIDrawConfig &config, + color clr = CLR_NONE // + ) + { + // + // Validate ... + bool has = trend.IsValid(); + if (!has) + { + return; + } + + // + color trendColor = + (clr != CLR_NONE) + ? clr + : trend.IsBullish() + ? config.bullishColor + : trend.IsBearish() + ? config.bearishColor + : config.neuturalColor; + string name = trend.GetObjectID(); + + // + CChartObjectTrend *object; + has = DrawTrendLine( + trend.fromValue, + trend.fromTime, + trend.toValue, + trend.toTime, + object, + name, + config.trendRayRight, + config.trendRayLeft // + ); + if (has) + { + // + // Apply Style ... + object.Color(trendColor); + object.Width(config.trendWidth); + object.Style(config.trendStyle); + + // + // Save Object ... + drawnObjects.Add(object); + } + + // + ZeroMemory(object); + } + + /** + * Draw Specified Pattern info ... + * + * @param _bar: XOHCL, reference to Pattern's Bar ... + * @param _pivot: XPivot, reference to Pattern's Pivot ... + * @param _zone: XBoxZone, reference to Pattern's Zone ... + * @param _pattern: ENUM_X_BAR_PATTERN, Specified Bar Pattern ... + * @param _patternDir: ENUM_X_DIRECTION, Specified Bar Pattern's Direction ... + * @param thresholdMultiplier: int, pivot point threshold ... + * @param config: XPOIDrawConfig, Darwing Configuration ... + */ + void DrawPattern( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_BAR_PATTERN _pattern, + ENUM_X_DIRECTION _patternDir, + XPOIDrawConfig &config, + int thresholdMultiplier = 0 // + ) + { + // + // Validate ... + bool has = + _bar.IsValid() && + IsXValid(_pattern) && + HasDirection(_patternDir); + if (!has) + { + return; + } + + // + datetime cTime = TimeCurrent(); + + // + // Handle Draws ... + + // + // Draw OHCL Bar ... + + // + // Draw Pivot ... + DrawPivot(_pivot, config, thresholdMultiplier); + + // + // Draw Zone ... + _zone.to = cTime; + DrawZone(_zone, config); + } + + /** + * Draw Specified Bar Pattern Analysis ... + * + * @param analysis: XPatternAnalysis, reference to Specified Bar Pattern Analysis ... + * @param config: XPatternAnalysisDrawConfig, reference to Provide Drawing Configuration ... + */ + void DrawPatternAnalysis( + XPatternAnalysis &analysis, + XPatternAnalysisDrawConfig &config // + ) + { + // + bool has = analysis.IsValid(); + if (!has) + { + return; + } + + // + bool canDraw; + bool isBullish; + bool isBearish; + XOHCL patternBar; + bool canDrawZone; + bool canDrawPivot; + XPivot patternPivot; + XBoxZone patternBox; + ENUM_X_BAR_PATTERN pattern; + ENUM_X_DIRECTION patternDir; + + // + datetime cTime = TimeCurrent(); + int patternsPivotThresholdMultiplier = 0; + + // + // Support and Resistance ... + + // + // Support ... + isBearish = false; + isBullish = analysis.IsSupport(); + has = isBullish; + if (has) + { + // + pattern = X_BAR_PATTERN_SUPPORT; + patternDir = X_DIRECTION_BULLISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Resistance ... + isBullish = false; + isBearish = analysis.IsResistance(); + has = isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_RESISTANCE; + patternDir = X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // PV: High and Low ... + + // + // Low ... + isBearish = false; + isBullish = analysis.IsLow(); + has = isBullish; + if (has) + { + // + pattern = X_BAR_PATTERN_LOW; + patternDir = X_DIRECTION_BULLISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // High ... + isBullish = false; + isBearish = analysis.IsHigh(); + has = isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_HIGH; + patternDir = X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // OB ... + isBullish = analysis.IsOB(X_DIRECTION_BULLISH); + isBearish = analysis.IsOB(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_OB; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // FVG ... + isBullish = analysis.IsFVG(X_DIRECTION_BULLISH); + isBearish = analysis.IsFVG(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_FVG; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Momentum ... + isBullish = analysis.IsMomentum(X_DIRECTION_BULLISH); + isBearish = analysis.IsMomentum(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_MOMENTUM; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Engulfed ... + isBullish = analysis.IsEngulfed(X_DIRECTION_BULLISH); + isBearish = analysis.IsEngulfed(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_ENGULFED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Pinned ... + isBullish = analysis.IsPinned(X_DIRECTION_BULLISH); + isBearish = analysis.IsPinned(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_PINNED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // TrueGaped ... + isBullish = analysis.IsTrueGaped(X_DIRECTION_BULLISH); + isBearish = analysis.IsTrueGaped(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_TRUE_GAPED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Star ... + isBullish = analysis.IsStar(X_DIRECTION_BULLISH); + isBearish = analysis.IsStar(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_STAR; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Piercing ... + isBullish = analysis.IsPiercing(X_DIRECTION_BULLISH); + isBearish = analysis.IsPiercing(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_PIERCING; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Rising ... + isBullish = analysis.IsRising(X_DIRECTION_BULLISH); + isBearish = analysis.IsRising(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_RISING; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Flag ... + isBullish = analysis.IsFlag(X_DIRECTION_BULLISH); + isBearish = analysis.IsFlag(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_FLAG; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // SignalKey ... + isBullish = analysis.IsSignalKey(X_DIRECTION_BULLISH); + isBearish = analysis.IsSignalKey(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_SIGNALKEY; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = analysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + config.drawConfig, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Cleanup Resources ... + patternBar.Clean(); + patternBox.Clean(); + patternPivot.Clean(); + } + + /** + * Draw a Collection of Pattern Analysis ... + * + * @param analysises: XPatternAnalysis, collection reference to Data Source ... + * @param config: XPatternAnalysisDrawConfig, reference to Specified Drawing Config ... + */ + void DrawPatternAnalysises( + XPatternAnalysis &analysises[], + XPatternAnalysisDrawConfig &config // + ) + { + // + bool has = HasChild(analysises); + if (!has) + { + return; + } + + // + int count = ArraySize(analysises); + for (int i = 0; i < count; i++) + { + DrawPatternAnalysis(analysises[i], config); + } + } + + /** + * Draw Specified Pivots Analysis ... + * + * @param analysis: XPivotAnalysis, reference to Specified Pivot Analysis ... + * @param config: XPivotAnalysisDrawConfig, reference to Provide Drawing Configuration ... + */ + void DrawPivotAnalysis( + XPivotAnalysis &analysis, + XPivotAnalysisDrawConfig &config // + ) + { + // + bool has = analysis.IsValid(); + if (!has) + { + return; + } + + // + int count = 0; + XBoxZone tmpBox; + datetime cTime = TimeCurrent(); + + // + // Pivots ... + if (config.drawPivots) + { + // + has = analysis.HasPivots(); + if (has) + { + // + count = ArraySize(analysis.pivots); + for (int i = 0; i < count; i++) + { + // + DrawPivot( + analysis.pivots[i], + config.drawConfig // + ); + } + } + } + + // + // Support ... + if (config.drawSupport) + { + // + tmpBox.Clean(); + has = analysis.HasSupportBox(tmpBox); + if (has) + { + // + tmpBox.to = cTime; + DrawZone( + tmpBox, + config.drawConfig // + ); + } + } + + // + // Resistance ... + if (config.drawResistance) + { + // + tmpBox.Clean(); + has = analysis.HasResistanceBox(tmpBox); + if (has) + { + // + tmpBox.to = cTime; + DrawZone( + tmpBox, + config.drawConfig // + ); + } + } + + // + // Peak Trend ... + if (config.drawPeakTrend) + { + // + has = analysis.IsPeakAnalysed(); + if (has) + { + // + string iUpperName = analysis.GetUpperObjectID(); + CChartObjectTrend *iObj = new CChartObjectTrend(); + has = iObj.Create( + ChartIdentification(), + iUpperName, + SubWindowIdentification(), + analysis.fromTime, + analysis.peakFrom, + analysis.toTime, + analysis.peakTo // + ); + if (has) + { + // + // Styling ... + iObj.RayLeft(config.rayLeftTrends); + iObj.RayRight(config.rayRightTrends); + iObj.Width(config.drawConfig.zonesWidth); + iObj.Style(config.drawConfig.zonesStyle); + iObj.Color(IsXBullish(analysis.peakDir) + ? config.drawConfig.bullishColor + : config.drawConfig.bearishColor); + + // + // Storing ... + drawnObjects.Add(iObj); + } + } + } + + // + // Vale Trend ... + if (config.drawValeTrend) + { + // + has = analysis.IsValeAnalysed(); + if (has) + { + // + string iLowerName = analysis.GetLowerObjectID(); + CChartObjectTrend *iObj = new CChartObjectTrend(); + has = iObj.Create( + ChartIdentification(), + iLowerName, + SubWindowIdentification(), + analysis.fromTime, + analysis.valeFrom, + analysis.toTime, + analysis.valeTo // + ); + if (has) + { + // + // Styling ... + iObj.RayLeft(config.rayLeftTrends); + iObj.RayRight(config.rayRightTrends); + iObj.Width(config.drawConfig.zonesWidth); + iObj.Style(config.drawConfig.zonesStyle); + iObj.Color(IsXBullish(analysis.valeDir) + ? config.drawConfig.bullishColor + : config.drawConfig.bearishColor); + + // + // Storing ... + drawnObjects.Add(iObj); + } + } + } + + // + // Cleanup ... + tmpBox.Clean(); + + // + } + + protected: + // + + // + private: + // + + // + // Props ... + + // + string mPrefix; // Prefix of Created Objects ... + long mChartIdentification; // Chart Id ... + int mSubWindowIdentification; // Sub Window ... + + // +}; \ No newline at end of file diff --git a/BKPS/14041018/Classes/x-saherelm.x-position.drawer.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-position.drawer.class.mq5 new file mode 100644 index 0000000..5e229d9 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-position.drawer.class.mq5 @@ -0,0 +1,482 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCPositionDrawer +// Description: Provides Position +// 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 "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +// Implementation ... + +class XCPositionDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + int window; // Window ID of Chart ... + ulong chartID; // Chart ID ... + XCTrade *trader; // XCTrade Instance ... + XPOIStyle riskStyle; // Risk Box Style ... + color inProfitColor; // In Profit Price Box Color ... + color inDrawdownColor; // In Drawdown Price Box Color ... + ENUM_LINE_STYLE priceStyle; // Price Box Style ... + XPOIStyle rewardStyle; // Reward Box Style ... + CArrayObj positionObjects; // Drawn Positions Object Instances Collection ... + CArrayObj finalizedObjects; // Finalized Drawn Positions Object Instances Collection ... + + // + // Constructor ... + XCPositionDrawer( + XCTrade *_trader, + ulong _chartID = 0, + int _window = 0 // + ) : XCBase() + { + // + Init( + _trader, + _chartID, + _window // + ); + } + + // + // Deconstructor ... + ~XCPositionDrawer() + { + Destroy(); + } + + // + // Tools ... + + /** + * Initialize Class Instance ... + * + * @param _trader: XCTrade, reference Pointer to Trader Instance Class ... + * @param _chartID: ulong, Specified Chart ID ... + * @param _window: int, Specified Chart Window ID ... + */ + void Init( + XCTrade *_trader, + ulong _chartID = 0, + int _window = 0 // + ) + { + // + // Validate ... + bool has = + _window >= 0 && + _chartID >= 0 && + _trader != NULL; + if (!has) + { + return; + } + + // + trader = _trader; + window = _window; + chartID = _chartID; + + // + // Prepare Default Styles ... + + // + // Risk Style ... + riskStyle.width = 1; + riskStyle.fill = false; + riskStyle.clr = clrRed; + riskStyle.style = STYLE_DASH; + + // + // Reward Style ... + rewardStyle.width = 1; + rewardStyle.fill = false; + rewardStyle.clr = clrLime; + rewardStyle.style = STYLE_DASH; + + // + // Price Style ... + priceStyle = STYLE_SOLID; + inProfitColor = clrAqua; // ApplyAlpha(clrAqua, 100); + inDrawdownColor = clrMagenta; // ApplyAlpha(clrMagenta, 100); + } + + /** + * Destroy Instance ... + */ + void Destroy() + { + // + riskStyle.Clean(); + rewardStyle.Clean(); + // positionObjects + // finalizedObjects + } + + /** + * Validate Instance ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + trader != NULL; + + // + return result; + } + + /** + * Update Positions ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void Update(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return; + } + + // + // Update Exists Positions ... + XPosition positions[]; + int positionsCount = trader.GetPositions(positions); + has = IsValidSize(positionsCount); + if (has) + { + // + int drawingsCount = positionObjects.Total(); + has = IsValidSize(drawingsCount); + if (has) + { + // + for (int i = 0; i < positionsCount; i++) + { + // + for (int j = 0; j < drawingsCount; j++) + { + // + // Check Object is Belong to Position ... + has = ((XCPositionObject *)positionObjects.At(j)).IsBelong(positions[i]); + if (has) + { + // + // Update Position Object ... + has = ((XCPositionObject *)positionObjects.At(j)).Update(positions[i]); + } + } + } + } + } + + // + // Update Test Positions ... + positionsCount = positionObjects.Total(); + has = + !HasChild(positions) && + IsValidSize(positionsCount); + if (has) + { + // + XPosition iPosition; + for (int i = 0; i < positionsCount; i++) + { + // + // Retrieve Position from Object ... + has = ((XCPositionObject *)positionObjects.At(i)).GetPosition(iPosition); + if (has) + { + // + // Manully Update Position ... + has = ((XCPositionObject *)positionObjects.At(i)).Update(barIndex); + } + } + + // + iPosition.Clean(); + } + } + + // + // Trade Event Handlers ... + + /** + * Add Executed Signal ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void AddExecutedSignal(XSignal &signal) + { + // + // Validate ... + bool has = + signal.IsValid() && + signal.IsExecuted(); + if (!has) + { + return; + } + + // + XPosition iPosition; + + // + // Check Position Exists ... + has = trader.GetPosition( + signal.positionId, + iPosition // + ); + // + // Initial by Testing Position ... + if (!has) + { + // + has = ToXPosition( + signal, + iPosition, + trader.GetMagicNumber(), + signal.positionId // + ); + } + + // + // Validate result ... + if (has) + { + // + XCPositionObject *iObj = new XCPositionObject(); + has = iObj.Create( + chartID, + window, + iPosition // + ); + if (has) + { + // + // Set Stylers to Position ... + iObj.riskStyle = riskStyle; + iObj.priceStyle = priceStyle; + iObj.rewardStyle = rewardStyle; + iObj.inProfitColor = inProfitColor; + iObj.inDrawdownColor = inDrawdownColor; + + // + // Add to Collection ... + positionObjects.Add(iObj); + } + } + + // + // Cleanup Resources ... + iPosition.Clean(); + } + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleStopLossTriggered(const XDeal &deal) + { + // + Finalize(deal.positionId); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + Finalize(deal.positionId); + } + + /** + * 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 // + ) + { + Finalize(ticket); + } + + /** + * 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 // + ) + { + // + // Detect Position Index ... + int index = FindIndex(ticket); + bool has = IsValidIndex(index); + if (!has) + { + return; + } + + // + // Get Position of Objects ... + XPosition _position; + has = ((XCPositionObject *)positionObjects.At(index)).GetPosition(_position); + if (has) + { + // + // Get Position of Trader Instance ... + has = trader.GetPosition( + ticket, + _position // + ); + if (has) + { + // + // Update Position ... + ((XCPositionObject *)positionObjects.At(index)).Update(_position); + } + } + + // + // Cleanup Resources ... + _position.Clean(); + } + + // + // Protected ... + protected: + // + + /** + * Finalize Specified Position ... + * Remove it From Position Objects and add it to Finalized Objects Cllection ... + * + * @param ticket: ulong, Specified Position Ticket ... + */ + void Finalize(ulong ticket) + { + // + int index = FindIndex(ticket); + bool has = IsValidIndex(index); + if (!has) + { + return; + } + + // + // XCPositionObject *iObj = positionObjects.At(index); + // positionObjects.Delete(index); + // finalizedObjects.Add(iObj); + } + + /** + * Find Specified Position Index ... + * + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( int ) + */ + int FindIndex(ulong ticket) + { + // + int result = -1; + + // + // Validate ... + int count = + NotEmptyZero(ticket) && + positionObjects.Total(); + bool has = IsValidSize(count); + if (!has) + { + return result; + } + + // + XPosition iPosition; + for (int i = 0; i < count; i++) + { + // + has = ((XCPositionObject *)positionObjects.At(i)).GetPosition(iPosition); + has = has && + iPosition.ticket == ticket; + if (has) + { + // + result = i; + break; + } + } + + // + // Cleanup Resources ... + iPosition.Clean(); + + // + return result; + } + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Classes/x-saherelm.x-restrictions.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-restrictions.class.mq5 new file mode 100644 index 0000000..435b230 --- /dev/null +++ b/BKPS/14041018/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/14041018/Classes/x-saherelm.x-rm.panel.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-rm.panel.class.mq5 new file mode 100644 index 0000000..718e446 --- /dev/null +++ b/BKPS/14041018/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) ... + XCRMPanel() + { + // + Default(); + } + + // + // Deconstructor ... + ~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/14041018/Classes/x-saherelm.x-signaller.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-signaller.class.mq5 new file mode 100644 index 0000000..4e51238 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-signaller.class.mq5 @@ -0,0 +1,742 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCBaseSignaller ... +// Description: Base Signaller Class ... +// +// - Create an Instance based on this ... +// - Attach Required Helpers for Indicator Usages ... +// - Override Virtual Methdos: +// - [] ProcessTick: Processing All Ticks +// - [] ProcessNewBar: Processing All New Bars +// - [] CheckForGuard: Check For Guards +// - [] NormalizeSignal: Normalizing Prepared Signal ... +// - [] CheckAdditionslSignallerValidations: Additional Class Validations +// +// - Dont Forget to Call OnSignal Event in Process Methods when +// a signal Appears ... +// +// - also Whenever you want you can call PrepareSignal Action to +// provide a Signal based on Current Market State ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Base Signaller Class" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +// +// Implementations ... +class XCBaseSignaller : public XCBase +{ + // + // Public ... + public: + // + // Props ... + string name; // Name ... + string symbol; // Symbol ... + ENUM_TIMEFRAMES period; // Period ... + + // + bool ignoreTargets; // Ignore Signal Targets ... + double slAdditionDistance; // SL Addition Distance ... + double maxAllowedRiskDistance; // Max Allowed Risk In Points ... + + // + // Restrictions ... + datetime restUntil; // Resting Time ... + int restingSignals; // Resting Signals ... + datetime lastSignalAt; // Holding Last Signal's Time ... + int restingDelay; // Resting Bars After Last Signal ... + int loosingTrades; // Loosing Trades ... + + // + TCanAnalyse canAnalyseEventListener; + + // + XCMarketPatternDetector *patternDetector; + + // + // Constructor ... + XCBaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) + { + // + // Assign Properties ... + name = _name; + symbol = _symbol; + period = _period; + + // + ignoreTargets = false; + slAdditionDistance = 0; + maxAllowedRiskDistance = 0; + + // + processAllTicks = _processAllTicks; + defaultSignalR2R = _defaultSignalR2R; + defaultSignalVolume = _defaultSignalVolume; + defaultSignalRiskInPoint = _defaultSignalRiskInPoint; + + // + // Normalize ... + defaultSignalR2R = NormalizeDouble(defaultSignalR2R, 1, 10); + defaultSignalVolume = NormalizeDouble(defaultSignalVolume, 0.01); + defaultSignalVolume = NormalizeVolume(defaultSignalVolume, symbol, 2); + defaultSignalRiskInPoint = NormalizeDouble(defaultSignalRiskInPoint, 10); + + // + // Set Dfault Values ... + mProcessedTicksCount = 0; + mLastCheckedBarTime = NULL; + + // + patternDetector = new XCMarketPatternDetector(); + } + + // + // Deconstructor ... + ~XCBaseSignaller() + { + // + // Cleanup Event Listeners ... + SpecifiedClean(onSignalEventListeners); + + // + delete patternDetector; + ZeroMemory(patternDetector); + } + + // + // Event Listeners ... + + /** + * Add On Signal Event Listener ... + * + * @param listener: TOnSignal instance ... + */ + void AddOnSignalEventHandler(TOnSignal listener) + { + // + // Validate ... + if (listener == NULL) + { + return; + } + + // + Add( + listener, + onSignalEventListeners // + ); + } + + // + // Actions ... + + /** + * Check Signaller Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(name) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + // + patternDetector != NULL && + // + CheckAdditionslSignallerValidations() + // + ; + + // + return result; + } + + /** + * Handling On Tick Event ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void OnTick(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 Rest Until ... + has = !IsXValid(restUntil) || (IsXValid(restUntil) && cBarTime > restUntil); + if (!has) + { + return; + } + + // + // Check Process Permissions ... + has = CanAnalyseMarket(cBarTime); + if (!has) + { + return; + } + + // + // Check if new Bar, Reset Processed Ticks Count ... + isNewBar = cBarTime > mLastCheckedBarTime; + if (isNewBar) + { + // + mProcessedTicksCount = 0; + ProcessNewBar(barIndex); + return; + } + + // + // Check Allow Process ... + // Process All Ticks ... + // Process New Bars ... + has = processAllTicks || + (!processAllTicks && isNewBar); + if (!has) + { + return; + } + + // + // Set Last Works ... + mProcessedTicksCount++; + mLastCheckedBarTime = cBarTime; + + // + ProcessTick(barIndex); + } + + // + // Virtuals ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + return true; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + /** + * Prepare Restrictions Update For Losing Trades ... + */ + void LoseTrade() + { + // + restingSignals++; + loosingTrades++; + } + + /** + * Prepare Restrictions For Winning Trades ... + */ + void WinTrade() + { + // + if (loosingTrades > 0) + { + loosingTrades--; + } + + // + if (restingSignals > 0) + { + restingSignals--; + } + } + + // + // Protected ... + protected: + // + // Props ... + + // + bool processAllTicks; // Specified Processing All Ticks or not ... + + // + int mProcessedTicksCount; // Prcoessed Ticks Count ... + datetime mLastCheckedBarTime; // Last Checked Bar Time ... + + // + double defaultSignalR2R; // Default Signal Risk To Reward Ratio ... + double defaultSignalVolume; // Default Signal Volume ... + double defaultSignalRiskInPoint; // Default Signal Risk In Point ... + + // + // Event Notifiers ... + + /** + * Notify OnSignal Event Listeners ... + * + * @param signal: XSignal, Specified Signal to Notify ... + */ + void NotifySignalEventListeners(XSignal &signal) + { + // + int count = ArraySize(onSignalEventListeners); + + // + // Validate ... + if (!IsValidSize(count) || !signal.IsValid()) + { + return; + } + + // + // Check Restrictions ... + if (HasRestrictions()) + { + // + bool ignore = HandleRestrictions(signal); + if (ignore) + { + return; + } + } + + // + // Do Notify ... + for (int i = 0; i < count; i++) + { + onSignalEventListeners[i](signal); + } + + // + lastSignalAt = signal.time; + } + + /** + * Calling Can Analyse Event Listeners ... + * Check Can Analayse Market or not ... + * + * @param time: datetime, Specified Time for Checking ... + * + * @return ( bool ) + */ + bool CanAnalyseMarket(datetime time = NULL) + { + // + bool result = false; + + // + // Normalize ... + time = NormalizeTime(time); + + // + // Validation ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = canAnalyseEventListener == NULL; + if (result) + { + return result; + } + + // + // Calling Can Analyse Event Listener ... + result = canAnalyseEventListener( + symbol, + period, + time // + ); + + // + return result; + } + + /** + * Preparing Default Signal ... + * + * @param signal: XSignal, holding result Signal ... + * @param forDir: ENUM_X_DIRECTION + * @param targets: XTarget Array, Provides Signal Targets (Price) ... + * @param r2r: double, Provides Signal (r2r), if not Provided uses Default R2R ... + * @param slPrice: double, Provides Signal SL Price, if not Provided uses riskInPoint ... + * @param riskInPoint: double, Provides Signal Risk Amount which Multiplied to Points, if not Provided uses DefaultRiskInPoint ... + * + * @return ( bool ) + */ + bool PrepareSignal( + XSignal &signal, + ENUM_X_DIRECTION forDir, + XTarget &targets[], // + double r2r = 0, + double slPrice = 0, + double riskInPoint = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + signal.Clean(); + + // + // Normalize ... + + // + // Validate ... + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsSpecifiedBullish(forDir); + + // + double point = GetPoints(symbol); + double spread = GetSpread(symbol); + double volume = defaultSignalVolume; + double entry = GetEntry(symbol, forDir); + + // + riskInPoint = riskInPoint > 0 && slPrice <= 0 + ? riskInPoint + : defaultSignalRiskInPoint; + double risk = (riskInPoint * point); + risk = slPrice > 0 + ? MathAbs(entry - slPrice) + : risk; + + // + r2r = r2r > 0 + ? r2r + : defaultSignalR2R; + double reward = (risk * r2r) + spread; + + // + double tp = + isBullish + ? entry + reward + : entry - reward; + + // + double sl = + isBullish + ? entry - risk + : entry + risk; + + // + // Filling Values ... + signal.tp = tp; + signal.sl = sl; + signal.entry = entry; + signal.provider = name; + signal.symbol = symbol; + signal.period = period; + signal.volume = volume; + signal.time = TimeCurrent(); + signal.type = + isBullish + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + signal.mode = X_ORDER_MODE_MARKET; + + // + // Apply Targets ... + if (HasChild(targets)) + { + // + ApplyTargetsOnSignal( + forDir, + targets, + signal // + ); + } + + // + // Validate Signal ... + result = signal.IsValid(); + if (result) + { + // + NormalizeSignal(signal); + result = signal.IsValid(); + } + + // + if (!result) + { + signal.Clean(); + } + + // + return result; + } + + /** + * Check Signaller Has Restrictions or not ... + * + * @return ( bool ) + */ + bool HasRestrictions() + { + // + bool result = false; + + // + result = + // + // Rest Delay ... + restingDelay > 0 || + // + // Resting Signals ... + restingSignals > 0 || + // + // Rest Until ... + IsXValid(restUntil) + // + ; + + // + return result; + } + + /** + * Handle Restrictions On Signal ... + * + * @param signal: XSignal, reference to Provided Sginal ... + * + * @return ( bool ) + */ + bool HandleRestrictions(XSignal &signal) + { + // + // Ignore Signal Execution ... + bool result = true; + + // + // Check Restrictions Exists ... + if (!HasRestrictions()) + { + // + // Disable Signal Ignoring and Allow Notify Signal ... + result = false; + return result; + } + + // + datetime cTime = TimeCurrent(); + + // + // Resting Signals ... + if (restingSignals > 0) + { + // + restingSignals--; + return result; + } + + // + // Rest Until ... + if (IsXValid(restUntil)) + { + // + if (cTime > restUntil) + { + // + restUntil = NULL; + + // + // Disable Signal Ignoring and Allow Notify Signal ... + result = false; + return result; + } + else + { + // + // Ignore Signal ... + return result; + } + } + + // + // Resting Delay ... + if (restingDelay > 0 && + IsXValid(lastSignalAt)) + { + // + int lastSignalIDX = GetBarIndex( + signal.symbol, + signal.period, + lastSignalAt // + ); + if (IsValidIndex(lastSignalIDX)) + { + // + if (lastSignalIDX > restingDelay) + { + // + restingDelay = 0; + // + // Disable Signal Ignoring and Allow Notify Signal ... + result = false; + return result; + } + else + { + // + // Ignore Signal ... + return result; + } + } + } + + // + return result; + } + + /** + * Reset All Restrictions ... + */ + void ResetRestrictions() + { + // + restingDelay = 0; + restUntil = NULL; + restingSignals = 0; + } + + // + // Private ... + private: + // + // Props ... + + // + // Event Listeners ... + TOnSignal onSignalEventListeners[]; +}; + +// diff --git a/BKPS/14041018/Classes/x-saherelm.x-target.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-target.class.mq5 new file mode 100644 index 0000000..1db8984 --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-target.class.mq5 @@ -0,0 +1,711 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XCTarget +// Description: provides all Positions Target 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-trade.class.mq5" + +// +// Implementation ... +class XCTarget : public XCBase +{ + // + // Public ... + public: + // + XCTrade *trader; + XCAlert *alert; + XSignal signals[]; + + // + // Constructor ... + XCTarget( + XCTrade *_trader, // + XCAlert *_alert // + ) : XCBase() + { + // + alert = _alert; + trader = _trader; + + // + XClean(signals); + } + + // + // Deconstructor ... + ~XCTarget() + { + Destroy(); + } + + // + void Destroy() + { + // + XClean(signals); + } + + // + // Actions ... + + /** + * Manage Positions ... + * + * @param barIndex: int, Bar Index ... + */ + void Manage(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Extract In Profit Positions ... + XPosition positions[]; + int count = GetInProfitPositions(positions); + bool has = IsValidIndex(count); + if (!has) + { + return; + } + + // + XSignal iSignal; + XTarget iTarget; + int signalIDX = -1; + int targetIDX = -1; + XPosition iPosition; + + // + // Loop through Positions ... + for (int i = 0; i < count; i++) + { + // + // Select Positions ... + iPosition = positions[i]; + has = FindSignal( + signalIDX, + iPosition.ticket // + ); + if (!has) + { + continue; + } + iSignal = signals[signalIDX]; + + // + // Selecting Target ... + targetIDX = iSignal.appliedTargetIDX; + if (iSignal.isTargetApplied) + { + targetIDX++; + } + + // + // Validate Targets Size ... + has = HasChild(iSignal.targets) && + targetIDX < ArraySize(iSignal.targets); + if (has) + { + // + // Select Target ... + iTarget = iSignal.targets[targetIDX]; + + // + // Check Can Apply Target and Apply it ... + has = HandleApplyTarget(iTarget, iPosition); + if (has) + { + // + // Update Target IDX ... + iSignal.appliedTargetIDX++; + } + } + + // + // Update Signal ... + signals[signalIDX] = iSignal; + + // + // Cleanup ... + iSignal.Clean(); + iTarget.Clean(); + iPosition.Clean(); + } + + // + // Cleanup Resources ... + iSignal.Clean(); + iTarget.Clean(); + iPosition.Clean(); + } + + /** + * Extract in Profit Positions ... + * + * @param positions: XPosition, reference collection to holds result ... + * + * @return ( int ) + */ + int GetInProfitPositions( + XPosition &positions[] // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(positions); + + // + // Validate ... + if (trader == NULL) + { + return result; + } + + // + result = trader.GetInProfitPositions( + positions, + NULL, // All Symbols ... + NULL, // All Providers ... + NULL, // All Periods ... + NULL, // All Position Types ... + X_POSITION_SELECT_ALL, // Select Method ... + true, // Filter by Magic ... + true // Force Clean ... + ); + if (IsValidSize(result)) + { + // + XPosition iPos; + XPosition tmp[]; + Copy( + positions, + tmp // + ); + XClean(positions); + while (HasChild(tmp)) + { + // + iPos = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + int idx = -1; + bool has = FindSignal( + idx, + iPos.ticket // + ); + if (has) + { + // + AddRef( + iPos, + positions // + ); + } + } + + // + XClean(tmp); + iPos.Clean(); + + // + result = ArraySize(positions); + } + + // + return result; + } + + /** + * Add Executed Signal ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void AddExecutedSignal(XSignal &signal) + { + // + // Validate ... + if (!signal.IsValid() || !signal.IsExecuted()) + { + return; + } + + // + AddRef( + signal, + signals // + ); + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + RemoveSignal(deal.positionId); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + RemoveSignal(deal.positionId); + } + + /** + * 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 // + ) + { + RemoveSignal(ticket); + } + + // + // Event Handlers Registration ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + // Protected ... + protected: + // + + /** + * Find Specified Signal ... + * + * @param index: int, reference to holds detected index ... + * @param signal: XSignal, reference to Specified Signal ... + * + * @return ( bool ) + */ + bool FindSignal( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + result = signal.IsValid() && + HasChild(signals); + if (!result) + { + return result; + } + + // + // Looping Through Signals ... + int count = ArraySize(signals); + for (int i = 0; i < count; i++) + { + // + result = signals[i] + .IsSameAs(signal); + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Specified Signal ... + * + * @param index: int, reference to holds detected index ... + * @param ticket: ulong, Specified Signal Position ID ... + * + * @return ( bool ) + */ + bool FindSignal( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + result = NotEmptyZero(ticket) && + HasChild(signals); + if (!result) + { + return result; + } + + // + // Looping Through Signals ... + int count = ArraySize(signals); + for (int i = 0; i < count; i++) + { + // + result = signals[i].IsValid() && + signals[i].IsExecuted() && + signals[i].positionId == ticket; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove Specified Signal ... + * + * @param ticket: ulong, Specified Ticket ... + */ + void RemoveSignal(ulong ticket) + { + // + bool has = NotEmptyZero(ticket) && + HasChild(signals); + if (!has) + { + return; + } + + // + int idx = -1; + has = FindSignal( + idx, + ticket // + ); + if (!has) + { + return; + } + + // + ArrayRemove( + signals, + idx, + 1 // + ); + } + + /** + * Check Can Apply Specified Target on Specified Position or not ... + * + * @param target: XTarget, reference to Specified Target for Apply ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool CanApplyTarget( + XTarget &target, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = + target.IsValid() && + position.IsValid(); + if (!result) + { + return result; + } + + // + // Check Price Reached Targets Value and Distance ... + double targetDistance = (target.actingDistance > 0 ? target.actingDistance : 0) * position.GetPointsValue(); + result = + IsLong(position.type) + ? position.price >= target.target + targetDistance + : position.price <= target.target - targetDistance; + + // + return result; + } + + /** + * Apply Specified Target on Specified Position ... + * + * @param target: XTarget, reference to Specified Target for Apply ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool HandleApplyTarget( + XTarget &target, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = + target.IsValid() && + position.IsValid() && + CanApplyTarget( + target, + position // + ); + if (!result) + { + return result; + } + + // + // Apply Target ... + string comment = NULL; + string message = NULL; + + // + // Do Risk Free if Provided ... + if (result && + target.doRF) + { + // + comment = "Taregt Manager do RF ..."; + result = trader.Modify( + position.ticket, + target.target, // SL ... + position.tp, // TP ... + comment // + ); + + // + // Handle Alert ... + if (result) + { + // + message = "Target Manager do RF " + ToXString(position.type) + " Position (" + ToXString(position.ticket) + ") on: " + ToXString(position.price); + alert.SendAlert(message); + } + } + + // + // Do Risk Free on Entry if Provided ... + if (result && + target.doRFOnEntry) + { + // + comment = "Target Manager do RF on Entry ..."; + double actingDistance = position.GetPointsValue() * target.actingDistance; + bool isLong = IsLong(position.type); + double sl = position.entry + (isLong + ? actingDistance + : (-1 * actingDistance) // + ); + result = trader.Modify( + position.ticket, + sl, // SL ... + position.tp, // TP ... + comment // + ); + + // + // Handle Alert ... + if (result) + { + // + message = "Target Manager do RF " + ToXString(position.type) + " Position (" + ToXString(position.ticket) + ") on Entry ..."; + alert.SendAlert(message); + } + } + + // + // Do Partial Close if Provided ... + if (result && + target.volumeMultiplier > 0) + { + // + double volume = NormalizeVolume((position.volume * target.volumeMultiplier), position.symbol); + if (volume != position.volume) + { + // + comment = "Target Manager do Partial Close ..."; + result = trader.ClosePartial( + position.ticket, + volume, + comment // + ); + + // + // Handle Alert ... + if (result) + { + // + message = "Target Manager do Partial Close " + ToXString(position.type) + " Position (" + ToXString(position.ticket) + ") by: " + ToXString(volume); + alert.SendAlert(message); + } + } + } + + // + // Handle Replace TP ... + if (result && + target.tpValue > 0) + { + // + // Validate TP Value ... + bool isLong = IsLong(position.type); + bool isValid = isLong + ? target.tpValue > position.price && + target.tpValue > position.tp + : target.tpValue < position.price && + target.tpValue < position.tp; + if (isValid) + { + // + comment = "Target Manager Change TP ..."; + result = trader.Modify( + position.ticket, + position.sl, // SL ... + target.tpValue, // TP ... + comment // + ); + + // + // Handle Alert ... + if (result) + { + // + message = "Target Manager Change TP of" + ToXString(position.type) + " Position (" + ToXString(position.ticket) + ") to: " + ToXString(target.tpValue) + " ..."; + alert.SendAlert(message); + } + } + } + + // + return result; + } + + // + // Private ... + private: + // + + // + // Required Event Handlers ... + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; +}; + +// diff --git a/BKPS/14041018/Classes/x-saherelm.x-trade-manager.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-trade-manager.class.mq5 new file mode 100644 index 0000000..4098a6b --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-trade-manager.class.mq5 @@ -0,0 +1,2429 @@ +/////////////////////////////////////////////////////// +// +// 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-target.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; + XCTarget *target; + XCVolume *volume; + XTimeTracker timeTracker; + XCDataCollector *collector; + + // + XCPOIDrawer *drawer; + + // + TCheckForGuard checkForGuardEventListener; + + // + // Constructor ... + XCTradeManager( + XCAlert *_alert, + XCTrade *_trader, + XCVolume *_volume, + XCGuard *_guard, + XCTarget *_target // + ) + { + // + alert = _alert; + guard = _guard; + volume = _volume; + trader = _trader; + target = _target; + + // + 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(); + + // + 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 hasName = iPartsCount >= 1; + bool hasSymbol = iPartsCount >= 2; + bool hasPeriod = iPartsCount >= 3; + bool hasSessionsDescriptor = iPartsCount >= 4; + bool hasMaxAllowedSpred = iPartsCount >= 5; + bool hasMaxAllowedPositios = iPartsCount >= 6; + bool hasRestrictionDescriptor = iPartsCount >= 7; + + // + // Parts IDX ... + int partsIDX = 0; + + // + // Extract Name ... + string iName = + hasName + ? iParts[partsIDX] + : ""; + iName = EscapeString(iName); + partsIDX++; + + // + // Extract Symbol ... + string iSymbol = + hasSymbol + ? iParts[partsIDX] + : _Symbol; + iSymbol = EscapeString(iSymbol); + iSymbol = NormalizeSymbol(iSymbol); + partsIDX++; + + // + // Extract Period ... + ENUM_TIMEFRAMES iPeriod = + hasPeriod + ? ToPeriod(EscapeString(iParts[partsIDX])) + : _Period; + iPeriod = NormalizePeriod(iPeriod); + partsIDX++; + + // + // Extract Sessions Descriptor ... + string iSessionsDescriptor = + hasSessionsDescriptor + ? iParts[partsIDX] + : ""; + iSessionsDescriptor = EscapeString(iSessionsDescriptor); + partsIDX++; + + // + // Extract Max Allowed Sspread ... + double iMaxAllowedSpread = + hasMaxAllowedSpred + ? (double)(EscapeString(iParts[partsIDX])) + : 25; + partsIDX++; + + // + // Extract Max Allowedd Positions ... + int iMaxAllowedPositions = + hasMaxAllowedPositios + ? (int)(EscapeString(iParts[partsIDX])) + : 5; + partsIDX++; + + // + // Extract Restrictions Descriptor ... + string iRestrictionsDescriptor = + hasRestrictionDescriptor + ? iParts[partsIDX] + : ""; + iRestrictionsDescriptor = EscapeString(iRestrictionsDescriptor); + partsIDX++; + + // + XSymbolTradeConfig iConfig; + + // + // Initialize Config ... + has = iConfig.Init( + iName, + 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(); + + // + // Managing Targets ... + target.Manage(); + + // + // 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; + } + + // + // Check Signal Spread ... + int idx = FindSymbolConfigurationIndex( + signal.symbol, + signal.period // + ); + if (IsValidIndex(idx)) + { + // + double spread = GetSpread(signal.symbol); + result = + symbolTradeConfigs[idx].maxAllowedSpread > 0 + ? spread <= symbolTradeConfigs[idx].maxAllowedSpread + : true; + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_SPREAD; + + // + return result; + } + + // + // Checking Max Allowed Positions ... + if (symbolTradeConfigs[idx].maxAllowedPositions > 0) + { + // + XPosition positions[]; + ENUM_X_POSITION_TYPES mType = IsLong(signal.type) + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + int positionsCount = trader.GetPositions( + positions, + symbolTradeConfigs[idx].symbol, + NULL, // All Providers ... + symbolTradeConfigs[idx].period, + mType, + true, // Filter By Magic ... + true // Force Clean ... + ); + result = !IsValidSize(positionsCount) || + (IsValidSize(positionsCount) && + positionsCount < symbolTradeConfigs[idx].maxAllowedPositions); + + // + // Cleanup Resources ... + SpecifiedClean(positions); + } + } + + // + 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) + { + // + // 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); + + // + target.HandleOnTakeProfitTriggered(deal); + } + + /** + * 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); + + // + target.HandleOnStopLossTriggered(deal); + } + + /** + * 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); + + // + target.HandleOnPositionForceClosed( + position.ticket, + position, + position.comment // + ); + } + + /** + * 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[] // + ) + { + } + + /** + * Handle Signal Executed Event ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void HandleSignalExecuted(XSignal &signal) + { + target.AddExecutedSignal(signal); + } + + // + // 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) + { + // + XPosition positions[]; + trader.GetPositions(positions); + result = checkForGuardEventListener(dest, positions, 0); + } + + // + 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( + "Default", + _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/14041018/Classes/x-saherelm.x-trade.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-trade.class.mq5 new file mode 100644 index 0000000..9af25ef --- /dev/null +++ b/BKPS/14041018/Classes/x-saherelm.x-trade.class.mq5 @@ -0,0 +1,3946 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + 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 + // + ); + } + + // + // Add New Signal Executed Event Handler ... + void AddOnSignalExecutedEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalExecutedEventHandlers // + ); + } + + // + // 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; + + // + // Notify Signal Execution ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + NotifySignalExecuted(mSignal); + } + } + + // + 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 // + ); + } + } + + // + void NotifySignalExecuted(XSignal &signal) + { + // + bool has = signal.IsValid() && + signal.IsExecuted(); + if (!has) + { + return; + } + + // + int count = ArraySize(mOnSignalExecutedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnSignal iHandler = mOnSignalExecutedEventHandlers[i]; + iHandler(signal); + } + } + + // + // 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[]; + + // + // Signal Executed Event Handlers ... + TOnSignal mOnSignalExecutedEventHandlers[]; + + // + 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/14041018/Classes/x-saherelm.x-volume.class.mq5 b/BKPS/14041018/Classes/x-saherelm.x-volume.class.mq5 new file mode 100644 index 0000000..09720c3 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/TestRegresser.mq5 b/BKPS/14041018/Documents/BKP/TestRegresser.mq5 new file mode 100644 index 0000000..5b14ef6 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/TestRegresser.mq5 @@ -0,0 +1,344 @@ +//+------------------------------------------------------------------+ +//| TestRegresser.mq5 | +//| SaherElm IT Center | +//| https://www.saherelm.ir | +//+------------------------------------------------------------------+ +#property copyright "SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include + +// +// Inputs ... +input int mLoopbackLength = 200; +input ENUM_X_PRICE mPriceType = X_PRICE_HIGH; + +// +// Calculation ... +input group "Calculation"; +input int zigzagDepth = 12; // Depth +input int zigzagDeviation = 5; // Deviation +input int zigzagBackStep = 3; // Back Step + +// +// Variables ... + +// +int mZigZagHandler = INVALID_HANDLE; + +// +// double mSumX = 0; +// double mSumY = 0; +// double mSumXY = 0; +// double mSumX2 = 0; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + double xData[]; + double yData[]; + int xDataCount = CollectData( + xData, + yData // + ); + + // + // Initialize ZigZag Handler ... + mZigZagHandler = iCustom( + _Symbol, + _Period, + "ZigZagColor", + zigzagDepth, + zigzagDeviation, + zigzagBackStep // + ); + if (mZigZagHandler == INVALID_HANDLE) + { + Print("Error creating ZigZag handle"); + return (INIT_FAILED); + } + + // // + // for (int i = 0; i < mLoopbackLength; i++) + // { + // // + // double iY = yData[i]; + // double iX = xData[i]; + + // // + // mSumX += iX; + // mSumY += iY; + // mSumXY += (iX * iY); + // mSumX2 += (iX * iX); + // } + + // // + // for (int i = 0; i < mLoopbackLength; i++) + // { + // // + // double iY = GetAppliedPrice( + // _Symbol, + // _Period, + // i, + // mPriceType // + // ); + // double iX = i + 1; + + // // + // mSumX += iX; + // mSumY += iY; + // mSumXY += (iX * iY); + // mSumX2 += (iX * iX); + // } + + // + // int n = mLoopbackLength; + // double slope = (n * mSumXY - mSumX * mSumY) / (n * mSumX2 - mSumX * mSumX); + // double intercept = (mSumY - slope * mSumX) / n; + + // // + // double xData[]; + // double yData[]; + // int xDataCount = CollectData( + // xData, + // yData // + // ); + double _cSlope; + double _cIntercept; + int calculatedCount = CalculateSlopeandIntercept( + _cSlope, + _cIntercept, + xData, + yData // + ); + + // + datetime time1 = iTime(_Symbol, _Period, mLoopbackLength); + datetime time2 = iTime(_Symbol, _Period, 0); + + // // + // double price1 = (intercept + slope * mLoopbackLength); + // double price2 = (intercept + slope); + + // + double cPrice1 = PredictValue( + _cSlope, + _cIntercept, + time1 // + ); + double cPrice2 = PredictValue( + _cSlope, + _cIntercept, + time2 // + ); + + // + string name = "TrendLine"; + string cName = "cTrendLine"; + + // + // CChartObjectTrend *iTrend = new CChartObjectTrend(); + // bool isCreated = iTrend.Create( + // ChartID(), + // name, + // 0, + // time1, + // price1, + // time2, + // price2 // + // ); + // if (isCreated) + // { + // // + // // Styling Trend Line ... + // } + + // + CChartObjectTrend *iCTrend = new CChartObjectTrend(); + bool isCreated = iCTrend.Create( + ChartID(), + cName, + 0, + time1, + cPrice1, + time2, + cPrice2 // + ); + if (isCreated) + { + // + // Styling Trend Line ... + } + + // + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + //--- +} +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + //--- +} +//+------------------------------------------------------------------+ + +// +int CollectData( + double &xData[], + double &yData[], + int barIndex = 0 // +) +{ + // + int result = false; + + // + SpecifiedClean(xData); + SpecifiedClean(yData); + + // + barIndex = NormalizeInt(barIndex, 0); + + // + int start = barIndex; + int end = start + mLoopbackLength; + for (int i = start; i < end; i++) + { + // + double iY = GetAppliedPrice( + _Symbol, + _Period, + i // + ); + + // + datetime iTime = iTime( + _Symbol, + _Period, + i // + ); + double iX = i + 1; // (double)TimeToSeconds(iTime); + + // + Add( + iX, + xData // + ); + + // + Add( + iY, + yData // + ); + } + + // + result = ArraySize(xData); + + // + return result; +} + +// +int CalculateSlopeandIntercept( + double &_slope, + double &_intercept, + double &xData[], + double &yData[] // +) +{ + // + int result = 0; + + // + bool has = false; + + // + _slope = 0; + _intercept = 0; + + // + if (!HasChild(xData) || + !HasChild(yData)) + { + return result; + } + + // + double sumX = 0; + double sumY = 0; + double sumXY = 0; + double sumX2 = 0; + + // + double x = 0; + double y = 0; + int end = MathMin(ArraySize(xData), ArraySize(yData)); + for (int i = 0; i < end; i++) + { + // + double x = xData[i]; + double y = yData[i]; + + // + sumX += x; + sumY += y; + sumXY += x * y; + sumX2 += x * x; + } + + // + int n = end; + _slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); + _intercept = (sumY - _slope * sumX) / n; + + // + result = n; + + // + return result; +} + +// +double PredictValue( + double &_slope, + double &_intercept, + datetime forTime // +) +{ + // + double result = 0; + + // + if (!IsSpecifiedValid(forTime)) + { + return result; + } + + // + double forX = iBarShift( + _Symbol, + _Period, + forTime // + ); // (double)TimeToSeconds(forTime); + result = (_intercept + _slope * forX); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/X121XKI/tmp.1.bkp.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/tmp.1.bkp.mq5 new file mode 100644 index 0000000..d33b68c --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/tmp.1.bkp.mq5 @@ -0,0 +1,1085 @@ + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int scoreBullish = 0; + int scoreBearish = 0; + bool isBullish = false; + bool isBearish = false; + int barIndex = bar.Index() + 1; + + // + // Initialize Indexed Bar ... + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // #region Market Structure ... + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone minorSupport; + XBoxZone majorSupport; + XBoxZone minorResistance; + XBoxZone majorResistance; + poiDetector.GetCurrentStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + barIndex, + bar.symbol, + iBar.period, // Minor ... + PERIOD_H1, // Major ... + 50, + 14, + 21, + 0 // + ); + + // + // Refining Zones ... + int refineLoopback = 500; + double refineBreakThreshold = 10; + ENUM_X_PRICE refineBreakBy = X_PRICE_CLOSE; + poiDetector.RefineStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + refineLoopback, + refineBreakThreshold, + refineBreakBy // + ); + // #endregion + + // #region Reading Conditions and Scoring ... + // + // ATR ... + bool isATRUp = kiParser.IsVolatilityHigh(barIndex) || + kiParser.IsVolatilitySwitchdToHigh(barIndex); + + // #region KI ... + // + bool isKIBullish = (kiParser.IsKIFastBullish(barIndex) || + kiParser.IsKIFastSwitchedToBullish(barIndex)) && + (kiParser.IsKISlowBullish(barIndex) || + kiParser.IsKISlowSwitchedToBullish(barIndex)); + if (isKIBullish) + { + scoreBullish++; + } + + // + bool isKIBearish = (kiParser.IsKIFastBearish(barIndex) || + kiParser.IsKIFastSwitchedToBearish(barIndex)) && + (kiParser.IsKISlowBearish(barIndex) || + kiParser.IsKISlowSwitchedToBearish(barIndex)); + if (isKIBearish) + { + scoreBearish++; + } + // #endregion + + // #region KI Wave ... + // + bool isKIWaveBullish = kiParser.IsKIWaveBullish(barIndex) || + kiParser.IsKIWaveSwitchedToBullish(barIndex); + if (isKIWaveBullish) + { + scoreBullish++; + } + + // + bool isKIWaveBearish = kiParser.IsKIWaveBearish(barIndex) || + kiParser.IsKIWaveSwitchedToBearish(barIndex); + if (isKIWaveBearish) + { + scoreBearish++; + } + // #endregion + + // #region MA ... + // + bool isMaBullish = kiParser.IsMACrossoverBullish(barIndex) || + kiParser.IsMACrossoverSwitchedToBullish(barIndex); + if (isMaBullish) + { + scoreBullish++; + } + + // + bool isMaBearish = kiParser.IsMACrossoverBearish(barIndex) || + kiParser.IsMACrossoverSwitchedToBearish(barIndex); + if (isMaBearish) + { + scoreBearish++; + } + // #endregion + + // #region LowerTF Candlstick ... + // + bool isLowerTFBullish = IsTFBullishPattern(barIndex, PERIOD_M5); + if (isLowerTFBullish) + { + scoreBullish++; + } + + // + bool isLowerTFBearish = IsTFBearishPattern(barIndex, PERIOD_M5); + if (isLowerTFBearish) + { + scoreBearish++; + } + // #endregion + + // #region Candlestick ... + // + bool isCandlestickBullish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BULLISH // + ); + if (isCandlestickBullish) + { + scoreBullish++; + } + + // + bool isCandlestickBearish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BEARISH // + ); + if (isCandlestickBearish) + { + scoreBearish++; + } + // #endregion + + // #region NearInside Support/Resistance ... + // + int tmpSupportIDX = -1; + bool isNearSupport = poiDetector.HasNearZone(tmpSupportIDX, iBar.close, 5, supports); + if (isNearSupport) + { + scoreBullish++; + } + + // + int tmpResistanceIDX = -1; + bool isNearResistance = poiDetector.HasNearZone(tmpResistanceIDX, iBar.close, 5, resistances); + if (isNearResistance) + { + scoreBearish++; + } + // #endregion + // #endregion + + // #region Summarize Directional Conditions ... + // + isBullish = + isATRUp && + scoreBullish >= 4 && + (isMaBullish || + isNearSupport || + isKIWaveBullish || + isLowerTFBullish || + isCandlestickBullish); + + // + isBearish = + isATRUp && + scoreBearish >= 4 && + (isMaBearish || + isNearResistance || + isKIWaveBearish || + isLowerTFBearish || + isCandlestickBearish); + // #endregion + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + return result; + } + + // + // Select Operational Zone ... + if (isBullish) + { + // + // Nearest Support ... + if (IsValidIndex(tmpSupportIDX)) + { + zone = supports[tmpSupportIDX]; + } + + // + // Make Sure Zone Exists ... + if (!zone.IsValid()) + { + // + // Looking Bar Patterns to Detect Zone ... + poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BULLISH); + } + } + else if (isBearish) + { + // + // Nearest Resistance ... + if (IsValidIndex(tmpResistanceIDX)) + { + zone = resistances[tmpResistanceIDX]; + } + + // + // Make Sure Zone Exists ... + if (!zone.IsValid()) + { + // + // Looking Bar Patterns to Detect Zone ... + poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BEARISH); + } + } + + // + // Refactor Result ... + result = result && + zone.IsValid(); + if (result) + { + // + // Refine Zone ... + poiDetector.RefineZone(zone); + + // + // SL Refactoring ... + + // + XOHCL toBar; + if (zone.ToBar(toBar)) + { + // + int to = zone.ToIndex(); + int from = zone.FromIndex(); + int length = from - to; + double iValue = + isBullish + ? toBar.FindLowest(length, MODE_LOW) + : isBearish + ? toBar.FindHighest(length, MODE_HIGH) + : EMPTY_VALUE; + if (NotEmptyZero(iValue)) + { + // + if (isBullish) + { + zone.lower = MathMin(zone.lower, iValue); + } + + // + if (isBearish) + { + zone.upper = MathMax(zone.upper, iValue); + } + } + } + toBar.Clean(); + } + + // + // Do Directional Validation ... + if (result) + { + // + // Bullish ... + if (isBullish) + { + // + isBullish = + isBullish && + isLowerTFBullish && + isCandlestickBullish; + } + + // + // Bearish ... + if (isBearish) + { + // + isBearish = + isBearish && + isLowerTFBearish && + isCandlestickBearish; + } + + // + result = isBullish || isBearish; + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate Result ... + if (!result) + { + // + iBar.Clean(); + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + return result; + } + + // + // Draws ... + bool draw = true; + if (draw && result) + { + // + int drawn = 0; + + // + XPOIDrawConfig config; + config.Default(); + + // + if (zone.IsValid()) + { + // + drawn++; + + // + config.zonesWidth = 3; + config.bullishColor = clrYellow; + config.bearishColor = clrOrange; + + // + poiDrawer.DrawZone(zone, config); + + // + config.Default(); + } + + // + // Minors ... + if (minorSupport.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(minorSupport, config); + } + if (minorResistance.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(minorResistance, config); + } + + // + // Majors ... + config.bullishColor = clrLime; + config.bearishColor = clrRed; + config.zonesWidth = 4; + + // + if (majorSupport.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(majorSupport, config); + } + if (majorResistance.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(majorResistance, config); + } + + // + config.Clean(); + + // + if (drawn > 0) + { + DebugBreak(); + } + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = result && + HasDirection(dir); + if (!result) + { + // + iBar.Clean(); + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + return result; + } + + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + if (result) + { + // + double upper = isBullish + ? entry + : zone.upper; + double lower = isBullish + ? zone.lower + : entry; + datetime to = bar.time; + datetime from = isBullish + ? zone.from + : zone.from; + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int scoreBullish = 0; + int scoreBearish = 0; + bool isBullish = false; + bool isBearish = false; + int barIndex = bar.Index() + 1; + + // + // Initialize Indexed Bar ... + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // #region Swings/OrderFlow ... + // + // Swings ... + XBoxZone swingLow; + XBoxZone swingHigh; + bool hasSwings = poiDetector.DetectRecentSwings( + swingHigh, + swingLow, + barIndex // + ); + + // + // Order Flow ... + + // + XBoxZone bullishOrderFlow[]; + result = poiDetector.HasOrderFlow(bullishOrderFlow, barIndex, 4, X_DIRECTION_BULLISH, 15); + + // + XBoxZone bearishOrderFlow[]; + result = poiDetector.HasOrderFlow(bearishOrderFlow, barIndex, 4, X_DIRECTION_BEARISH, 15); + // #endregion + + // #region Reading Conditions and Scoring ... + // + // ATR ... + bool isATRUp = kiParser.IsVolatilityHigh(barIndex) || + kiParser.IsVolatilitySwitchdToHigh(barIndex); + + // #region KI ... + // + bool isKIReadyForBullish = ((kiParser.IsKIFastBearish(barIndex) || + (kiParser.IsKIFastBullish(barIndex) && + iBar.IsRejected(kiHelper.GetKIFast(barIndex), X_DIRECTION_BULLISH))) && + kiParser.IsKISlowBullish(barIndex)); + + // + bool isKIReadyForBearish = ((kiParser.IsKIFastBullish(barIndex) || + (kiParser.IsKIFastBearish(barIndex) && + iBar.IsRejected(kiHelper.GetKIFast(barIndex), X_DIRECTION_BEARISH))) && + kiParser.IsKISlowBearish(barIndex)); + + // + bool isKIBandBullish = (kiHelper.GetKIUpper(barIndex) > kiHelper.GetKIUpper(barIndex + 1) || + kiHelper.GetKILower(barIndex) > kiHelper.GetKILower(barIndex + 1)); + + // + bool isKIBandBearish = (kiHelper.GetKIUpper(barIndex) < kiHelper.GetKIUpper(barIndex + 1) || + kiHelper.GetKILower(barIndex) < kiHelper.GetKILower(barIndex + 1)); + + // + bool isKIBullish = (kiParser.IsKIFastBullish(barIndex) || + kiParser.IsKIFastSwitchedToBullish(barIndex)) && + (kiParser.IsKISlowBullish(barIndex) || + kiParser.IsKISlowSwitchedToBullish(barIndex)); + if (isKIBullish) + { + scoreBullish++; + } + + // + bool isKIBearish = (kiParser.IsKIFastBearish(barIndex) || + kiParser.IsKIFastSwitchedToBearish(barIndex)) && + (kiParser.IsKISlowBearish(barIndex) || + kiParser.IsKISlowSwitchedToBearish(barIndex)); + if (isKIBearish) + { + scoreBearish++; + } + // #endregion + + // #region KI Wave ... + // + bool isKIWaveBullish = kiParser.IsKIWaveBullish(barIndex) || + kiParser.IsKIWaveSwitchedToBullish(barIndex); + if (isKIWaveBullish) + { + scoreBullish++; + } + + // + bool isKIWaveBearish = kiParser.IsKIWaveBearish(barIndex) || + kiParser.IsKIWaveSwitchedToBearish(barIndex); + if (isKIWaveBearish) + { + scoreBearish++; + } + // #endregion + + // #region MA ... + // + bool isMaBullish = kiParser.IsMACrossoverBullish(barIndex) || + kiParser.IsMACrossoverSwitchedToBullish(barIndex); + if (isMaBullish) + { + scoreBullish++; + } + + // + bool isMaBearish = kiParser.IsMACrossoverBearish(barIndex) || + kiParser.IsMACrossoverSwitchedToBearish(barIndex); + if (isMaBearish) + { + scoreBearish++; + } + // #endregion + + // #region LowerTF Candlstick ... + // + bool isLowerTFBullish = IsTFBullishPattern(barIndex, PERIOD_M5); + if (isLowerTFBullish) + { + scoreBullish++; + } + + // + bool isLowerTFBearish = IsTFBearishPattern(barIndex, PERIOD_M5); + if (isLowerTFBearish) + { + scoreBearish++; + } + // #endregion + + // #region Candlestick ... + // + bool isCandlestickBullish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BULLISH // + ); + if (isCandlestickBullish) + { + scoreBullish++; + } + + // + bool isCandlestickBearish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BEARISH // + ); + if (isCandlestickBearish) + { + scoreBearish++; + } + // #endregion + // #endregion + + // #region Summarize Directional Conditions ... + // + isBullish = + isATRUp && + isLowerTFBullish && + isKIReadyForBullish && + isCandlestickBullish && + scoreBullish >= 2 && + (isKIBullish || + isMaBullish || + isKIWaveBullish || + isKIBandBullish); + + // + isBearish = + isATRUp && + isLowerTFBearish && + isKIReadyForBearish && + isCandlestickBearish && + scoreBearish >= 2 && + (isKIBearish || + isMaBearish || + isKIWaveBearish || + isKIBandBearish); + // #endregion + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Select Operational Zone ... + ENUM_X_DIRECTION patternsDir[]; + ENUM_X_BAR_PATTERN patterns[]; + + // + // GetAllBarPatters(patterns, patternsDir); + + // + // XAUUSD ... + + // + // FVG ... + Add(X_BAR_PATTERN_FVG, patterns); + Add(X_DIRECTION_NONE, patternsDir); + + // + // Piercing ... + Add(X_BAR_PATTERN_PIERCING, patterns); + Add(X_DIRECTION_NONE, patternsDir); + + // + // EURUSD ... + + // + // Add(X_BAR_PATTERN_STAR, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // // + // Add(X_BAR_PATTERN_SUPPORT, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // // + // Add(X_BAR_PATTERN_RESISTANCE, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // + // Add(X_BAR_PATTERN_SIGNALKEY, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // + int nearestOrderFlowIDX = -1; + if (isBullish) + { + // + // Looking Bar Patterns to Detect Zone ... + isBullish = + isBullish && + HasChild(bullishOrderFlow) && + // bullishOrderFlow[0].lower == iBar.low && + // poiDetector.HasNearZone( + // nearestOrderFlowIDX, + // iBar.close, + // 5, + // bullishOrderFlow // + // ) && + poiDetector.HasRecentPatternTouched( + zone, + patterns, + patternsDir, + iBar.close, + barIndex, + 5, + 5, + iBar.period, + X_DIRECTION_BULLISH // + ); + } + else if (isBearish) + { + // + // Looking Bar Patterns to Detect Zone ... + isBearish = + isBearish && + HasChild(bearishOrderFlow) && + // bearishOrderFlow[0].upper == iBar.high && + // poiDetector.HasNearZone( + // nearestOrderFlowIDX, + // iBar.close, + // 5, + // bearishOrderFlow // + // ) && + poiDetector.HasRecentPatternTouched( + zone, + patterns, + patternsDir, + iBar.close, + barIndex, + 5, + 5, + iBar.period, + X_DIRECTION_BEARISH // + ); + } + + // + // Refactor Result ... + result = result && + zone.IsValid(); + if (result) + { + // + // Refine Zone ... + poiDetector.RefineZone(zone); + + // + // SL Refactoring ... + + // + XOHCL toBar; + if (zone.ToBar(toBar)) + { + // + int to = zone.ToIndex(); + int from = zone.FromIndex(); + int length = from - to; + double iValue = + isBullish + ? toBar.FindLowest(length, MODE_LOW) + : isBearish + ? toBar.FindHighest(length, MODE_HIGH) + : EMPTY_VALUE; + if (NotEmptyZero(iValue)) + { + // + if (isBullish) + { + zone.lower = MathMin(zone.lower, iValue); + } + + // + if (isBearish) + { + zone.upper = MathMax(zone.upper, iValue); + } + } + } + toBar.Clean(); + } + + // + // Do Directional Validation ... + if (result) + { + // + // Bullish ... + if (isBullish) + { + // + isBullish = + isBullish && + isLowerTFBullish && + isCandlestickBullish; + } + + // + // Bearish ... + if (isBearish) + { + // + isBearish = + isBearish && + isLowerTFBearish && + isCandlestickBearish; + } + + // + result = isBullish || isBearish; + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate Result ... + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Draws ... + bool draw = true; + if (draw && result) + { + // + int drawn = 0; + + // + XPOIDrawConfig config; + config.Default(); + + // + if (zone.IsValid()) + { + // + drawn++; + + // + config.zonesWidth = 3; + config.bullishColor = clrYellow; + config.bearishColor = clrOrange; + + // + poiDrawer.DrawZone(zone, config); + + // + config.Default(); + } + + // + if (swingLow.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(swingLow, config); + } + + // + if (swingHigh.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(swingHigh, config); + } + + // + if (HasChild(bullishOrderFlow)) + { + // + drawn += ArraySize(bullishOrderFlow); + poiDrawer.DrawZones(bullishOrderFlow, config); + } + + // + if (HasChild(bearishOrderFlow)) + { + // + drawn += ArraySize(bearishOrderFlow); + poiDrawer.DrawZones(bearishOrderFlow, config); + } + + // + if (drawn > 0) + { + // DebugBreak(); + } + + // + config.Clean(); + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = result && + HasDirection(dir); + if (result) + { + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + + // + double upper = isBullish + ? entry + : zone.upper; + double lower = isBullish + ? zone.lower + : entry; + datetime to = bar.time; + datetime from = isBullish + ? zone.from + : zone.from; + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + swingLow.Clean(); + XClean(patterns); + swingHigh.Clean(); + XClean(patternsDir); + XClean(bullishOrderFlow); + XClean(bearishOrderFlow); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } diff --git a/BKPS/14041018/Documents/BKP/X121XKI/tmp.poi.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/tmp.poi.mq5 new file mode 100644 index 0000000..d73516d --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/tmp.poi.mq5 @@ -0,0 +1,1726 @@ + +// #region XDetectors ... +bool IsKIPOI( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + bool isBullish = IsKIBullishPOI(barIndex); + bool isBearish = IsKIBearishPOI(barIndex); + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + return result; +} + +bool IsKIBullishPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = + kiParser.IsValid() && + kiParser.IsKISlowBullish(barIndex) && + kiParser.IsKIFastBearish(barIndex); + + // + return result; +} + +bool IsKIBearishPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = + kiParser.IsValid() && + kiParser.IsKISlowBearish(barIndex) && + kiParser.IsKIFastBullish(barIndex); + + // + return result; +} + +bool IsKISignal( + ENUM_X_DIRECTION &dir, // + int barIndex = 0 // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Retrieve KI State ... + bool isBullish = kiParser.IsKIFastSwitchedToBullish(barIndex + 1) && + kiParser.IsKIFastBullish(barIndex) && + kiParser.IsKISlowBullish(barIndex); + bool isBearish = kiParser.IsKIFastSwitchedToBearish(barIndex + 1) && + kiParser.IsKIFastBearish(barIndex) && + kiParser.IsKISlowBearish(barIndex); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex + 1); + if (!result) + { + return result; + } + + // + // Bar Direction Same as Dir ... + + // + // Price Place Check ... + double kiFast = kiHelper.GetKIFast(barIndex + 1); + double kiSlow = kiHelper.GetKISlow(barIndex + 1); + isBullish = + isBullish && + bar.close > kiFast && + kiFast > kiSlow && + (kiParser.IsKIFastOverLast(barIndex + 1) || + kiParser.IsKISlowOverLast(barIndex + 1)); + isBearish = + isBearish && + bar.close < kiFast && + kiFast < kiSlow && + (kiParser.IsKIFastUnderLast(barIndex + 1) || + kiParser.IsKISlowUnderLast(barIndex + 1)); + + // + result = + result && + (isBullish || + isBearish); + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} +// #endregion + +// #region Detectors ... +bool IsPOI( + ENUM_X_DIRECTION &forDir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + forDir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = IsBullishPOI(barIndex); + bool isBearish = IsBearishPOI(barIndex); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(forDir); + + // + return result; +} + +bool IsBullishPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendBullish(barIndex) && + kiParser.IsRSIBullish(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BULLISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsBearishPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendBearish(barIndex) && + kiParser.IsRSIBearish(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BEARISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsBreakoutPOI( + ENUM_X_DIRECTION &forDir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + forDir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = IsBullishBreakoutPOI(barIndex); + bool isBearish = IsBearishBreakoutPOI(barIndex); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(forDir); + + // + return result; +} + +bool IsBullishBreakoutPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsBullishBreakout(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BULLISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsBearishBreakoutPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsBearishBreakout(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BEARISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsReversalPOI( + ENUM_X_DIRECTION &forDir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + forDir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = IsBullishReversalPOI(barIndex); + bool isBearish = IsBearishReversalPOI(barIndex); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(forDir); + + // + return result; +} + +bool IsBullishReversalPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsBullishReversal(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BULLISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsBearishReversalPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsBearishReversal(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BEARISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsContinuationPOI( + ENUM_X_DIRECTION &forDir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + forDir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = IsBullishContinuationPOI(barIndex); + bool isBearish = IsBearishContinuationPOI(barIndex); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(forDir); + + // + return result; +} + +bool IsBullishContinuationPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendStrongBullish(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + XOHCL swingBar; + result = result && + IsFlagPattern(bar, dir, swingBar) && + IsXBullish(dir); + + // + bar.Clean(); + swingBar.Clean(); + + // + return result; +} + +bool IsBearishContinuationPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendStrongBearish(barIndex); + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + XOHCL swingBar; + result = result && + IsFlagPattern(bar, dir, swingBar) && + IsXBearish(dir); + + // + bar.Clean(); + swingBar.Clean(); + + // + return result; +} + +bool IsExhaustionPOI( + ENUM_X_DIRECTION &forDir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + forDir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = IsBullishExhaustionPOI(barIndex); + bool isBearish = IsBearishExhaustionPOI(barIndex); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(forDir); + + // + return result; +} + +bool IsBullishExhaustionPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isTrendOk = kiParser.IsTrendStrongBullish(barIndex); + bool isRSIOk = kiParser.IsRSIOverbought(barIndex); + result = isTrendOk && isRSIOk; + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BEARISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsBearishExhaustionPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isTrendOk = kiParser.IsTrendStrongBearish(barIndex); + bool isRSIOk = kiParser.IsRSIOversold(barIndex); + result = isTrendOk && isRSIOk; + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BULLISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsTrendExhaustedPOI( + ENUM_X_DIRECTION &forDir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + forDir = X_DIRECTION_NONE; + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = IsBullishTrendExhaustedPOI(barIndex); + bool isBearish = IsBearishTrendExhaustedPOI(barIndex); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(forDir); + + // + return result; +} + +bool IsBullishTrendExhaustedPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Trend was strong in last 3 bars ... + bool isTrendOk = kiParser.IsTrendStrongBullish(barIndex + 1); + for (int i = 1; i <= 3; i++) + { + // + if (kiParser.IsTrendStrongBullish(barIndex + i)) + { + isTrendOk = true; + break; + } + } + + // + // RSI rolling over from overbought ... + double rsiNow = kiHelper.GetRSI(barIndex); + double rsiPrev = kiHelper.GetRSI(barIndex + 1); + bool rsiFlip = (rsiPrev > 70 && rsiNow < rsiPrev); + bool isRSIOk = rsiFlip || kiParser.IsRSIOverbought(barIndex); + + // + bool volCooling = kiHelper.GetATR(barIndex) <= kiHelper.GetATRSmoothed(barIndex) * 1.05; + bool isVolatilityOk = volCooling || kiParser.IsVolatilityLow(barIndex); + + // + result = isRSIOk && + isTrendOk && + isVolatilityOk; + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BEARISH // + ); + + // + bar.Clean(); + + // + return result; +} + +bool IsBearishTrendExhaustedPOI(int barIndex = 0) +{ + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isTrendOk = kiParser.IsTrendStrongBearish(barIndex + 1); + for (int i = 1; i <= 3; i++) + { + // + if (kiParser.IsTrendStrongBearish(barIndex + i)) + { + isTrendOk = true; + break; + } + } + + // + // RSI rolling over from overbought ... + double rsiNow = kiHelper.GetRSI(barIndex); + double rsiPrev = kiHelper.GetRSI(barIndex + 1); + bool rsiFlip = (rsiPrev < 30 && rsiNow > rsiPrev); + bool isRSIOk = rsiFlip || kiParser.IsRSIOversold(barIndex); + + // + bool volCooling = kiHelper.GetATR(barIndex) <= kiHelper.GetATRSmoothed(barIndex) * 1.05; + bool isVolatilityOk = volCooling || kiParser.IsVolatilityLow(barIndex); + + // + result = isRSIOk && + isTrendOk && + isVolatilityOk; + if (!result) + { + return result; + } + + // + // Add candlestick confirmation ... + XOHCL bar; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + HasCandlestickDirection( + bar, + X_DIRECTION_BULLISH // + ); + + // + bar.Clean(); + + // + return result; +} +// #endregion + +// #region POI Detectors ... +bool NearestKIFastBullish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKIFastBearish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKIFastSwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastSwitchedToBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKIFastSwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastSwitchedToBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKISlowBullish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKISlowBearish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKISlowSwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowSwitchedToBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool NearestKISlowSwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 50 // +) +{ + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowSwitchedToBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} +// #endregion + +// #region Composite ... +bool IsTrendBullish(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIFastBullish(barIndex) && + IsKISlowBullish(barIndex) && + IsMACrossoverBullish(barIndex); + + // + return result; +} + +bool IsTrendBearish(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIFastBearish(barIndex) && + IsKISlowBearish(barIndex) && + IsMACrossoverBearish(barIndex); + + // + return result; +} + +bool IsBullishMomentumTrend(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsTrendBullish(barIndex) && + IsRSIBullish(barIndex); + + // + return result; +} + +bool IsBearishMomentumTrend(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsTrendBearish(barIndex) && + IsRSIBearish(barIndex); + + // + return result; +} + +bool IsBullishBreakout(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + IsPriceAboveKIUpper(barIndex) && + IsATRBreakoutUp(barIndex) && + IsVolatilityHigh(barIndex); + + // + return result; +} + +bool IsBearishBreakout(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + IsPriceBelowKILower(barIndex) && + IsATRBreakoutDown(barIndex) && + IsVolatilityHigh(barIndex); + return result; +} + +bool IsBullishReversal(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // RSI oversold and turning upward ... + double rsiNow = helper.GetRSI(barIndex); + double rsiPrev = helper.GetRSI(barIndex + 1); + bool rsiFlip = (rsiNow > rsiPrev) && (rsiPrev < 30); + + // + // ATR check (volatility supportive) ... + double atrNow = helper.GetATR(barIndex); + double atrPrev = helper.GetATR(barIndex + 1); + double atrMaNow = helper.GetATRSmoothed(barIndex); + double atrMaPrev = helper.GetATRSmoothed(barIndex + 1); + bool atrOk = atrNow > atrMaNow || atrNow > atrPrev || atrMaNow > atrMaPrev; + + // + // MA crossover bullish ... + double maFastNow = helper.GetMAFast(barIndex); + double maSlowNow = helper.GetMASlow(barIndex); + bool maOk = maFastNow > maSlowNow; + + // + result = rsiFlip && (atrOk || maOk); + + // + return result; +} + +bool IsBearishReversal(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // RSI overbought and turning downward ... + double rsiNow = helper.GetRSI(barIndex); + double rsiPrev = helper.GetRSI(barIndex + 1); + bool rsiFlip = (rsiNow < rsiPrev) && (rsiPrev > 70); + + // + // ATR check (volatility supportive) ... + double atrNow = helper.GetATR(barIndex); + double atrPrev = helper.GetATR(barIndex + 1); + double atrMaNow = helper.GetATRSmoothed(barIndex); + double atrMaPrev = helper.GetATRSmoothed(barIndex + 1); + bool atrOk = atrNow > atrMaNow || atrNow > atrPrev || atrMaNow > atrMaPrev; + + // + // MA crossover bearish ... + double maFastNow = helper.GetMAFast(barIndex); + double maSlowNow = helper.GetMASlow(barIndex); + bool maOk = maFastNow < maSlowNow; + + // + result = rsiFlip && (atrOk || maOk); + + // + return result; +} + +bool IsSafeBullishEntry(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsBullishMomentumTrend(barIndex) && !IsRSIOverbought(barIndex); + return result; +} + +bool IsSafeBearishEntry(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsBearishMomentumTrend(barIndex) && !IsRSIOversold(barIndex); + return result; +} + +bool IsTrendStrongBullish(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Strong bullish trend requires: + // - KI Fast bullish + // - KI Slow bullish + // - MA crossover bullish + // - RSI > 60 + // - Volatility high + result = IsKIFastBullish(barIndex) && + IsKISlowBullish(barIndex) && + IsMACrossoverBullish(barIndex) && + (helper.GetRSI(barIndex) > 60) && + IsVolatilityHigh(barIndex); + + // + return result; +} + +bool IsTrendStrongBearish(int barIndex = 0) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Strong bearish trend requires: + // - KI Fast bearish + // - KI Slow bearish + // - MA crossover bearish + // - RSI < 40 + // - Volatility high + result = IsKIFastBearish(barIndex) && + IsKISlowBearish(barIndex) && + IsMACrossoverBearish(barIndex) && + (helper.GetRSI(barIndex) < 40) && + IsVolatilityHigh(barIndex); + + // + return result; +} + +/** + * Counting Touches ... + * + * @param bullish: int reference to holds bullih touches ... + * @param bearish: int reference to holds bearish touches ... + * @param barIndex: int, start Bar Index ... + * @param loopback: int, loopback length for counting ... + * @param countKIFast: boolean, Count KI Fast ... + * @param countKISlow: boolean, Count KI Slow ... + * @param countKIUpper: boolean, Count KI Upper ... + * @param countKILower: boolean, Count KI Lower ... + * @param countMAFast: boolean, Count MA Fast ... + * @param countMASlow: boolean, Count MA Slow ... + * @param forceClean: boolean, Force Clean results before Start Counting ... + * @param priceType: ENUM_X_BOUNDARY_PRICE, Specified Price Type for Boundary Countinf ... + */ +void CountTouches( + int &bullish, + int &bearish, + int barIndex = 0, + int loopback = 5, + bool countKIFast = true, + bool countKISlow = true, + bool countKIUpper = true, + bool countKILower = true, + bool countMAFast = true, + bool countMASlow = true, + bool forceClean = true, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // +) +{ + // + if (forceClean) + { + bullish = 0; + bearish = 0; + } + + // + // KI Fast ... + if (countKIFast) + { + // + // Bullish ... + bullish += CountKIFastTouches( + barIndex, + loopback, + X_DIRECTION_BULLISH, + priceType // + ); + + // + // Bearish ... + bearish += CountKIFastTouches( + barIndex, + loopback, + X_DIRECTION_BEARISH, + priceType // + ); + } + + // + // KI Slow ... + if (countKISlow) + { + // + // Bullish ... + bullish += CountKISlowTouches( + barIndex, + loopback, + X_DIRECTION_BULLISH, + priceType // + ); + + // + // Bearish ... + bearish += CountKISlowTouches( + barIndex, + loopback, + X_DIRECTION_BEARISH, + priceType // + ); + } + + // + // KI Upper ... + if (countKIUpper) + { + // + // Bullish ... + bullish += CountKIUpperTouches( + barIndex, + loopback, + X_DIRECTION_BULLISH, + priceType // + ); + + // + // Bearish ... + bearish += CountKIUpperTouches( + barIndex, + loopback, + X_DIRECTION_BEARISH, + priceType // + ); + } + + // + // KI Lower ... + if (countKILower) + { + // + // Bullish ... + bullish += CountKILowerTouches( + barIndex, + loopback, + X_DIRECTION_BULLISH, + priceType // + ); + + // + // Bearish ... + bearish += CountKILowerTouches( + barIndex, + loopback, + X_DIRECTION_BEARISH, + priceType // + ); + } + + // + // KI MA Fast ... + if (countMAFast) + { + // + // Bullish ... + bullish += CountMAFastTouches( + barIndex, + loopback, + X_DIRECTION_BULLISH, + priceType // + ); + + // + // Bearish ... + bearish += CountMAFastTouches( + barIndex, + loopback, + X_DIRECTION_BEARISH, + priceType // + ); + } + + // + // KI MA Slow ... + if (countMASlow) + { + // + // Bullish ... + bullish += CountMASlowTouches( + barIndex, + loopback, + X_DIRECTION_BULLISH, + priceType // + ); + + // + // Bearish ... + bearish += CountMASlowTouches( + barIndex, + loopback, + X_DIRECTION_BEARISH, + priceType // + ); + } +} +// #endregion diff --git a/BKPS/14041018/Documents/BKP/X121XKI/tmp.signaller.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/tmp.signaller.mq5 new file mode 100644 index 0000000..fba5377 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/tmp.signaller.mq5 @@ -0,0 +1,320 @@ + + // #region Signals ... + + // #region POI ... + bool IsBullishPOILongEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + // IMPORTANT: Use near Support/Resistance ... + bool result = poiDetector.IsBullishPOI(barIndex) && + kiParser.IsSafeBullishEntry(barIndex) && + IsTFBullishPattern(barIndex, lowerTF); + + // + return result; + } + + bool IsBearishPOIShortEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + // IMPORTANT: Use near Support/Resistance ... + bool result = poiDetector.IsBearishPOI(barIndex) && + kiParser.IsSafeBearishEntry(barIndex) && + IsTFBearishPattern(barIndex, lowerTF); + + // + return result; + } + + bool ExitBullishPOILong(int barIndex = 0) + { + // + bool result = + poiDetector.IsBearishReversalPOI(barIndex) || + poiDetector.IsBearishBreakoutPOI(barIndex) || + poiDetector.IsBearishExhaustionPOI(barIndex); + + // + return result; + } + + bool ExitBearishPOIShort(int barIndex = 0) + { + // + bool result = + poiDetector.IsBullishReversalPOI(barIndex) || + poiDetector.IsBullishBreakoutPOI(barIndex) || + poiDetector.IsBullishExhaustionPOI(barIndex); + + // + return result; + } + // #endregion + + // #region Breakout ... + bool IsBreakoutLongEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = false; + + // + result = + kiParser.IsVolatilityHigh(barIndex) && + IsTFBullishPattern(barIndex, lowerTF) && + poiDetector.IsBullishBreakoutPOI(barIndex); + + // + return result; + } + + bool IsBreakoutShortEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = false; + + // + result = + kiParser.IsVolatilityHigh(barIndex) && + IsTFBearishPattern(barIndex, lowerTF) && + poiDetector.IsBearishBreakoutPOI(barIndex); + + // + return result; + } + + bool ExitBreakoutLong(int barIndex = 0) + { + // + bool result = + poiDetector.IsBearishReversalPOI(barIndex) || + poiDetector.IsBearishExhaustionPOI(barIndex); + + // + return result; + } + + bool ExitBreakoutShort(int barIndex = 0) + { + // + bool result = + poiDetector.IsBullishReversalPOI(barIndex) || + poiDetector.IsBullishExhaustionPOI(barIndex); + + // + return result; + } + // #endregion + + // #region Reversal ... + bool IsReversalLongEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + kiParser.IsRSIBullish(barIndex) && + IsTFBullishPattern(barIndex, lowerTF) && + poiDetector.IsBullishReversalPOI(barIndex); + + // + return result; + } + + bool IsReversalShortEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + kiParser.IsRSIBearish(barIndex) && + IsTFBearishPattern(barIndex, lowerTF) && + poiDetector.IsBearishReversalPOI(barIndex); + + // + return result; + } + + bool ExitReversalLong(int barIndex = 0) + { + // + bool result = + poiDetector.IsBearishBreakoutPOI(barIndex) || + poiDetector.IsBearishContinuationPOI(barIndex); + + // + return result; + } + + bool ExitReversalShort(int barIndex = 0) + { + // + bool result = + poiDetector.IsBullishBreakoutPOI(barIndex) || + poiDetector.IsBullishContinuationPOI(barIndex); + + // + return result; + } + // #endregion + + // #region Continuation ... + bool IsContinuationLongEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + IsTFBullishPattern(barIndex, lowerTF) && + kiParser.IsTrendStrongBullish(barIndex) && + poiDetector.IsBullishContinuationPOI(barIndex); + + // + return result; + } + + bool IsContinuationShortEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + IsTFBearishPattern(barIndex, lowerTF) && + kiParser.IsTrendStrongBearish(barIndex) && + poiDetector.IsBearishContinuationPOI(barIndex); + + // + return result; + } + + bool ExitContinuationLong(int barIndex = 0) + { + // + bool result = + poiDetector.IsBearishReversalPOI(barIndex) || + poiDetector.IsBearishExhaustionPOI(barIndex); + + // + return result; + } + + bool ExitContinuationShort(int barIndex = 0) + { + // + bool result = + poiDetector.IsBullishReversalPOI(barIndex) || + poiDetector.IsBullishExhaustionPOI(barIndex); + + // + return result; + } + // #endregion + + // #region Exhaustion ... + bool IsExhaustionLongEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + IsTFBullishPattern(barIndex, lowerTF) && + poiDetector.IsBearishExhaustionPOI(barIndex); + + // + return result; + } + + bool IsExhaustionShortEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + IsTFBearishPattern(barIndex, lowerTF) && + poiDetector.IsBullishExhaustionPOI(barIndex); + + // + return result; + } + + bool ExitExhaustionLong(int barIndex = 0) + { + return poiDetector.IsBearishBreakoutPOI(barIndex); + } + + bool ExitExhaustionShort(int barIndex = 0) + { + return poiDetector.IsBullishBreakoutPOI(barIndex); + } + // #endregion + + // #region Trend Exhaustion ... + bool IsTrendExhaustionLongEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + IsTFBullishPattern(barIndex, lowerTF) && + poiDetector.IsBearishTrendExhaustedPOI(barIndex); + + // + return result; + } + + bool IsTrendExhaustionShortEntry( + int barIndex = 0, + ENUM_TIMEFRAMES lowerTF = PERIOD_M5 // + ) + { + // + bool result = + IsTFBearishPattern(barIndex, lowerTF) && + poiDetector.IsBullishTrendExhaustedPOI(barIndex); + + // + return result; + } + + bool ExitTrendExhaustionLong(int barIndex = 0) + { + // + bool result = + poiDetector.IsBearishBreakoutPOI(barIndex) || + poiDetector.IsBearishContinuationPOI(barIndex); + + // + return result; + } + + bool ExitTrendExhaustionShort(int barIndex = 0) + { + // + bool result = + poiDetector.IsBullishBreakoutPOI(barIndex) || + poiDetector.IsBullishContinuationPOI(barIndex); + + // + return result; + } + // #endregion + + // #endregion diff --git a/BKPS/14041018/Documents/BKP/X121XKI/tmp.xki.helper.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/tmp.xki.helper.mq5 new file mode 100644 index 0000000..8309b23 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/tmp.xki.helper.mq5 @@ -0,0 +1,825 @@ + + int CountKIFastTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetKIFast(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountKISlowTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetKISlow(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountKISuperSlowTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetKISuperSlow(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountKIUpperTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetKIUpper(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountKILowerTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetKILower(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountMAFastTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetMAFast(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountMASlowTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetMASlow(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + + int CountMASuperSlowTouches( + int barIndex = 0, + int loopback = 5, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iValue = 0; + double affectedValue = 0; + double iConfirnValue = 0; + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + ENUM_X_PRICE bullishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bullishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + ENUM_X_PRICE bearishTouchUpperPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + ENUM_X_PRICE bearishTouchLowerPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, period, i); + if (!has) + { + continue; + } + + // + affectedValue = helper.GetMASuperSlow(i); + + // + // Bullish Touches ... + if (isBullish) + { + // + iValue = iBar.GetPrice(bullishTouchLowerPriceType); + iConfirnValue = iBar.GetPrice(bullishTouchUpperPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue <= affectedValue && + iConfirnValue >= affectedValue; + if (has) + { + result++; + } + } + + // + // Bearish Touches ... + if (isBearish) + { + // + iValue = iBar.GetPrice(bearishTouchUpperPriceType); + iConfirnValue = iBar.GetPrice(bearishTouchLowerPriceType); + has = + NotEmptyZero(iValue) && + NotEmptyZero(affectedValue) && + NotEmptyZero(iConfirnValue) && + iValue >= affectedValue && + iConfirnValue <= affectedValue; + if (has) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + diff --git a/BKPS/14041018/Documents/BKP/X121XKI/tmp.zones.poi.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/tmp.zones.poi.mq5 new file mode 100644 index 0000000..973afd8 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/tmp.zones.poi.mq5 @@ -0,0 +1,458 @@ + + int CounteZoneTouches( + XBoxZone &zone, + double threshold = 10, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + threshold = NormalizeDouble(threshold, 10); + + // + if (!zone.IsValid()) + { + return result; + } + + // + XOHCL tmpBar; + int start = zone.ToIndex(); + bool isUpperTouched = false; + bool isLowerTouched = false; + double points = GetPoints(zone.symbol); + double distance = points * threshold; + int end = MathMin(start + loopback, zone.FromIndex()); + for (int i = start; i < end; i++) + { + // + if (tmpBar.Init(zone.symbol, zone.period, i)) + { + // + isUpperTouched = MathAbs(tmpBar.high - zone.upper) <= distance; + isLowerTouched = MathAbs(tmpBar.low - zone.lower) <= distance; + + // + if ( + (zone.IsBullish() && + (isLowerTouched || + MathAbs(tmpBar.close - zone.lower) <= distance)) || + (zone.IsBearish() && + (isUpperTouched || + MathAbs(tmpBar.close - zone.upper) <= distance))) + { + // + result++; + Add( + tmpBar.time, + zone.tests // + ); + } + + // + tmpBar.Clean(); + } + } + + // + tmpBar.Clean(); + + // + return result; + } + + bool HasNearZone( + int &index, + double price, + double threshold, + XBoxZone &zones[] // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Validate ... + result = HasChild(zones) && + NotEmptyZero(price) && + NotEmptyZero(threshold) && + price > 0 && + threshold > 0; + if (!result) + { + return result; + } + + // + double points = GetPoints(zones[0].symbol); + double distance = points * threshold; + for (int i = 0; i < ArraySize(zones); i++) + { + // + // Check Price Distance by Upper ... + result = price >= zones[i].lower - distance && + price <= zones[i].upper + distance; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool IsNearZone( + double price, + XBoxZone &zone, + double threshold = 0 // + ) + { + // + bool result = false; + + // + result = + zone.IsValid() && + NotEmptyZero(price); + if (!result) + { + return result; + } + + // + double points = GetPoints(zone.symbol); + double distance = points * threshold; + + // + result = price >= zone.lower - distance && + price <= zone.upper + distance; + + // + return result; + } + + + /* + * Check Recently Pattern Zone is Touched or not ... + * + * @param zone: XBoxZone, Touched Zone ... + * @param patterns: ENUM_X_BAR_PATTERN, Allowed to Check Patterns ... + * @param patternsDir: ENUM_X_DIRECTION, Allowed Directions ... + * @param price: double, a Price to Check Toch or Reject ... + * @param barIndex: int, Bar Index to Start Checking ... + * @param loopback: int, Loopback for Pattern Formations ... + * @param threshold: double, threshold for Pattern touch ... + * @param forPeriod: ENUM_TIMEFRAMES, Time Frame to Check Patterns ... + * @param forDir: ENUM_X_DIRECTION, Directions for Pattern's Formation Check ... + * + * @return ( bool ) + */ + bool HasRecentPatternTouched( + XBoxZone &zone, + ENUM_X_BAR_PATTERN &patterns[], + ENUM_X_DIRECTION &patternsDir[], + double price, + int barIndex = 0, + int loopback = 5, + double threshold = 5, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + // Validate ... + result = + HasChild(patterns) && + NotEmptyZero(price) && + HasChild(patternsDir) && + ArraySize(patterns) == ArraySize(patternsDir); + if (!result) + { + return result; + } + + // + // Normalize ... + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL iBar; + bool has = false; + int iBullishIDX = -1; + int iBearishIDX = -1; + bool isBullish = false; + bool isBearish = false; + XBoxZone iBullishZones[]; + XBoxZone iBearishZones[]; + XPatternAnalysis iAnalysis; + XPatternAnalysisConfig iConfig; + + // + // Preparing Pattern Analysis Config ... + iConfig.Default(); + + // + Copy( + patterns, + iConfig.allowedPatterns // + ); + Copy( + patternsDir, + iConfig.allowedDirs // + ); + + // + // XAUUSD ... + iConfig.AddPattern(X_BAR_PATTERN_FVG); + iConfig.AddPattern(X_BAR_PATTERN_PIERCING); + + // + // Looping Back ... + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Initialize Bar ... + has = iBar.Init(symbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Analyse Patterns ... + has = AnalyseBarPatterns(iBar, iAnalysis, iConfig); + if (!has) + { + // + iBar.Clean(); + continue; + } + + // + // Bullish ... + has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH); + has = HasChild(iBullishZones); + if (has) + { + // + has = HasNearZone( + iBullishIDX, + price, + threshold, + iBullishZones // + ); + if (has) + { + isBullish = true; + } + } + } + + // + // Bearish ... + has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH); + has = HasChild(iBearishZones); + if (has) + { + // + has = HasNearZone( + iBearishIDX, + price, + threshold, + iBearishZones // + ); + if (has) + { + isBearish = true; + } + } + } + + // + // Summarizing Result ... + has = + HasDirection(forDir) + ? (isBullish && !isBearish && IsXBullish(forDir)) || + (isBearish && !isBullish && IsXBearish(forDir)) + : (isBullish && !isBearish) || (isBearish && !isBullish); + if (has) + { + // + // Fill Zones ... + if (isBullish) + { + zone = iBullishZones[iBullishIDX]; + } + else + { + zone = iBearishZones[iBearishIDX]; + } + break; + } + + // + // Cleanup Resource ... + iBar.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iConfig.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + + // + return result; + } + + + void ValidateZones( + XBoxZone &zones[], + int barIndex = 0, + int minimumRetests = 2, + double retestThreshold = 10, + int retestLoopback = 100, + ENUM_X_BOUNDARY_PRICE forPriceType = X_BOUNDARY_PRICE_UP_DOWN // + ) + { + // + bool has = false; + + // + // Validation ... + has = HasChild(zones) && + IsXValid(forPriceType); + if (!has) + { + return; + } + + // + // Normalizetion ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + minimumRetests = NormalizeInt(minimumRetests, 0); + retestLoopback = NormalizeInt(retestLoopback, 50); + retestThreshold = NormalizeDouble(retestThreshold, 5, 10); + + // + XOHCL tmpBar; + XBoxZone tmp; + XBoxZone tmps[]; + double tmpValue = 0; + for (int i = 0; i < ArraySize(zones); i++) + { + // + tmp = zones[i]; + + // + if (minimumRetests > 0) + { + // + int retests = CounteZoneTouches(tmp, retestThreshold, retestLoopback); + if (retests < minimumRetests) + { + continue; + } + } + + // + // Validate Zone ... + has = false; + for (int j = barIndex; j < tmp.FromIndex(); j++) + { + // + // Initial Bar ... + if (tmpBar.Init(tmp.symbol, tmp.period, j)) + { + // + tmpValue = forPriceType == X_BOUNDARY_PRICE_UP_DOWN + ? tmp.IsBullish() + ? tmpBar.GetDown() + : tmpBar.GetUp() + : forPriceType == X_BOUNDARY_PRICE_HIGH_LOW + ? tmp.IsBullish() + ? tmpBar.low + : tmpBar.high + : EMPTY_VALUE; + if (NotEmptyZero(tmpValue)) + { + // + // Check Break ... + has = tmp.IsBullish() + ? tmpValue < tmp.lower + : tmpValue > tmp.upper; + + // + // If Breakes ... + if (has) + { + break; + } + } + + // + tmpBar.Clean(); + } + } + + // + // Not Breaked ... + if (!has) + { + // + AddIfNotExists( + tmp, + tmps // + ); + } + + // + tmp.Clean(); + } + + // + // Update Zones ... + XClean(zones); + Copy( + tmps, + zones // + ); + XClean(tmps); + } diff --git a/BKPS/14041018/Documents/BKP/X121XKI/tmps.bkp.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/tmps.bkp.mq5 new file mode 100644 index 0000000..6a733b9 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/tmps.bkp.mq5 @@ -0,0 +1,2127 @@ +/** + * Check Bar Has Signal Based on Strategy 1 ... + * + * Pattern‑based reversal: + * - Detects Pin Bar or Signal Key Bar. + * - Confirms with POI detector. + * - Good for reversals at support/resistance. + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = poiDetector.IsKISignal( + dir, + bar.Index() // + ); + bool isBullish = result && + IsXBullish(dir); + bool isBearish = result && + IsXBearish(dir); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Detect Nearest Directional ... + int nearestDirectionalSwitchIndex = -1; + if (isBullish) + { + // + isBullish = poiDetector.NearestKIFastSwitchedToBullish( + nearestDirectionalSwitchIndex, + bar.Index() + 2 // + ); + } + else + { + // + isBearish = poiDetector.NearestKIFastSwitchedToBearish( + nearestDirectionalSwitchIndex, + bar.Index() + 2 // + ); + } + result = + IsValidIndex(nearestDirectionalSwitchIndex) && + (isBullish || + isBearish); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Preparing Zone ... + double upper = bar.FindHighest(nearestDirectionalSwitchIndex - bar.Index(), MODE_HIGH); + double lower = bar.FindLowest(nearestDirectionalSwitchIndex - bar.Index(), MODE_LOW); + + // + result = zone.Init( + symbol, + period, + upper, + lower, + GetBarTime(symbol, period, nearestDirectionalSwitchIndex), + bar.time, + dir, + "XKI1" // + ); + + // + // Support and Resistance ... + XBoxZone supports[]; + XBoxZone resistances[]; + if (result) + { + // + // Supports ... + poiDetector.DetectSupports( + supports, + bar.Index(), + 50, // Loopback ... + true, // Force Validation ... + 7, // Validation Length ... + symbol, // For Symbol ... + period // For Period ... + ); + + // + // Resistances ... + poiDetector.DetectResistances( + resistances, + bar.Index(), + 50, // Loopback ... + true, // Force Validation ... + 7, // Validation Length ... + symbol, // For Symbol ... + period // For Period ... + ); + } + + // + // TODO: Rempve ... + if (result) + { + // + // Other Drawing Materials ... + XPOIDrawConfig drawConfig; + drawConfig.Default(); + + // + // this for Selected Zone ... + poiDrawer.DrawZone(zone, drawConfig); + + // + // Drawing Supports and Resistances ... + drawConfig.bearishColor = clrRed; + drawConfig.bullishColor = clrLime; + + // + if (HasChild(supports)) + { + poiDrawer.DrawZones(supports, drawConfig); + } + + // + if (HasChild(resistances)) + { + poiDrawer.DrawZones(resistances, drawConfig); + } + + // + drawConfig.Clean(); + + // + DebugBreak(); + } + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; +} + +/** + * Check Bar Has Signal Based on Strategy 1 ... + * + * Pattern‑based reversal: + * - Detects Pin Bar or Signal Key Bar. + * - Confirms with POI detector. + * - Good for reversals at support/resistance. + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = poiDetector.IsKISignal( + dir, + bar.Index() // + ); + bool isBullish = result && + IsXBullish(dir); + bool isBearish = result && + IsXBearish(dir); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Detect Nearest Directional ... + int nearestDirectionalSwitchIndex = -1; + if (isBullish) + { + // + isBullish = poiDetector.NearestKIFastSwitchedToBullish( + nearestDirectionalSwitchIndex, + bar.Index() + 2 // + ); + } + else + { + // + isBearish = poiDetector.NearestKIFastSwitchedToBearish( + nearestDirectionalSwitchIndex, + bar.Index() + 2 // + ); + } + result = + IsValidIndex(nearestDirectionalSwitchIndex) && + (isBullish || + isBearish); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Preparing Zone ... + double upper = bar.FindHighest(nearestDirectionalSwitchIndex - bar.Index(), MODE_HIGH); + double lower = bar.FindLowest(nearestDirectionalSwitchIndex - bar.Index(), MODE_LOW); + + // + result = zone.Init( + symbol, + period, + upper, + lower, + GetBarTime(symbol, period, nearestDirectionalSwitchIndex), + bar.time, + dir, + "XKI1" // + ); + + // + // Support and Resistance ... + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone minorSupport; + XBoxZone majorSupport; + XBoxZone minorResistance; + XBoxZone majorResistance; + if (result) + { + // + // Supports ... + poiDetector.GetCurrentStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + bar.Index(), + symbol, // For Symbol ... + period, // For Period ... + 50, // Loopback ... + 7, // Minor Validation Length ... + 14 // Major Validation Length ... + ); + } + + // + // TODO: Rempve ... + if (result) + { + // + // Other Drawing Materials ... + XPOIDrawConfig drawConfig; + drawConfig.Default(); + + // + // this for Selected Zone ... + poiDrawer.DrawZone(zone, drawConfig); + + // + // Drawing Supports and Resistances ... + drawConfig.bearishColor = clrRed; + drawConfig.bullishColor = clrLime; + + // + // Minors ... + + // + drawConfig.zonesStyle = STYLE_DOT; + if (minorSupport.IsValid()) + { + poiDrawer.DrawZone(minorSupport, drawConfig); + } + if (minorResistance.IsValid()) + { + poiDrawer.DrawZone(minorResistance, drawConfig); + } + + // + // Majors ... + + // + drawConfig.zonesStyle = STYLE_DASH; + if (majorSupport.IsValid()) + { + poiDrawer.DrawZone(majorSupport, drawConfig); + } + if (majorResistance.IsValid()) + { + poiDrawer.DrawZone(majorResistance, drawConfig); + } + + // // + // if (HasChild(supports)) + // { + // poiDrawer.DrawZones(supports, drawConfig); + // } + + // // + // if (HasChild(resistances)) + // { + // poiDrawer.DrawZones(resistances, drawConfig); + // } + + // + drawConfig.Clean(); + + // + DebugBreak(); + } + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; +} + +/** + * Check Bar Has Signal Based on Strategy 1 ... + * + * Pattern‑based reversal: + * - Detects Pin Bar or Signal Key Bar. + * - Confirms with POI detector. + * - Good for reversals at support/resistance. + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = poiDetector.IsKISignal( + dir, + bar.Index() // + ); + bool isBullish = result && + IsXBullish(dir); + bool isBearish = result && + IsXBearish(dir); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Detect Nearest Directional ... + int nearestDirectionalSwitchIndex = -1; + if (isBullish) + { + // + isBullish = poiDetector.NearestKIFastSwitchedToBullish( + nearestDirectionalSwitchIndex, + bar.Index() + 2 // + ); + } + else + { + // + isBearish = poiDetector.NearestKIFastSwitchedToBearish( + nearestDirectionalSwitchIndex, + bar.Index() + 2 // + ); + } + result = + IsValidIndex(nearestDirectionalSwitchIndex) && + (isBullish || + isBearish); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Preparing Zone ... + double upper = bar.FindHighest(nearestDirectionalSwitchIndex - bar.Index(), MODE_HIGH); + double lower = bar.FindLowest(nearestDirectionalSwitchIndex - bar.Index(), MODE_LOW); + + // + result = zone.Init( + symbol, + period, + upper, + lower, + GetBarTime(symbol, period, nearestDirectionalSwitchIndex), + bar.time, + dir, + "XKI1" // + ); + + // + // Support and Resistance ... + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone minorSupport; + XBoxZone majorSupport; + XBoxZone minorResistance; + XBoxZone majorResistance; + if (result) + { + // + // Supports ... + poiDetector.GetCurrentStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + bar.Index(), + symbol, // For Symbol ... + period, // For Period ... + 50, // Loopback ... + 7, // Minor Validation Length ... + 14 // Major Validation Length ... + ); + } + + // + // TODO: Rempve ... + if (result) + { + // + // Other Drawing Materials ... + XPOIDrawConfig drawConfig; + drawConfig.Default(); + + // + // this for Selected Zone ... + poiDrawer.DrawZone(zone, drawConfig); + + // + // Drawing Supports and Resistances ... + drawConfig.bearishColor = clrRed; + drawConfig.bullishColor = clrLime; + + // + // Minors ... + + // + drawConfig.zonesStyle = STYLE_DOT; + if (minorSupport.IsValid()) + { + poiDrawer.DrawZone(minorSupport, drawConfig); + } + if (minorResistance.IsValid()) + { + poiDrawer.DrawZone(minorResistance, drawConfig); + } + + // + // Majors ... + + // + drawConfig.zonesStyle = STYLE_DASH; + if (majorSupport.IsValid()) + { + poiDrawer.DrawZone(majorSupport, drawConfig); + } + if (majorResistance.IsValid()) + { + poiDrawer.DrawZone(majorResistance, drawConfig); + } + + // // + // if (HasChild(supports)) + // { + // poiDrawer.DrawZones(supports, drawConfig); + // } + + // // + // if (HasChild(resistances)) + // { + // poiDrawer.DrawZones(resistances, drawConfig); + // } + + // + drawConfig.Clean(); + + // + DebugBreak(); + } + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; +} + +/** + * Check Bar Has Signal Based on Strategy 1 ... + * + * Pattern‑based reversal: + * - Detects Pin Bar or Signal Key Bar. + * - Confirms with POI detector. + * - Good for reversals at support/resistance. + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Safe for Entry ... + bool isSafeForBullishEntry = kiParser.IsSafeBullishEntry(barIndex); + bool isSafeForBearishEntry = kiParser.IsSafeBearishEntry(barIndex); + + // + // POI ... + bool isPOI = poiDetector.IsPOI(dir, barIndex); + bool isBullishPOI = isPOI && + IsXBullish(dir); + bool isBearishPOI = isPOI && + IsXBearish(dir); + if (isPOI) + { + // + // Print("isPOI: ", ToXString(dir)); + // DebugBreak(); + } + + // + // Breakout POI ... + bool isBreakoutPOI = poiDetector.IsBreakoutPOI(dir, barIndex); + bool isBullishBreakoutPOI = isBreakoutPOI && + IsXBullish(dir); + bool isBearishBreakoutPOI = isBreakoutPOI && + IsXBearish(dir); + if (isBreakoutPOI) + { + // + // Print("isBreakoutPOI: ", ToXString(dir)); + // DebugBreak(); + } + + // + // Reversal POI ... + bool isReversalPOI = poiDetector.IsReversalPOI(dir, barIndex); + bool isBullishReversalPOI = isReversalPOI && + IsXBullish(dir); + bool isBearishReversalPOI = isReversalPOI && + IsXBearish(dir); + if (isReversalPOI) + { + // // + // Print("isReversalPOI: ", ToXString(dir)); + // DebugBreak(); + } + + // + // Continuation POI ... + bool isContinuationPOI = poiDetector.IsContinuationPOI(dir, barIndex); + bool isBullishContinuationPOI = isContinuationPOI && + IsXBullish(dir); + bool isBearishContinuationPOI = isContinuationPOI && + IsXBearish(dir); + if (isContinuationPOI) + { + // + // Print("isContinuationPOI: ", ToXString(dir)); + // DebugBreak(); + } + + // + // Exhaustion POI ... + bool isExhaustionPOI = poiDetector.IsExhaustionPOI(dir, barIndex); + bool isBullishExhaustionPOI = isExhaustionPOI && + IsXBullish(dir); + bool isBearishExhaustionPOI = isExhaustionPOI && + IsXBearish(dir); + if (isExhaustionPOI) + { + // + // Print("isExhaustionPOI: ", ToXString(dir)); + // DebugBreak(); + } + + // + // TrendExhausted POI ... + bool isTrendExhaustedPOI = poiDetector.IsTrendExhaustedPOI(dir, barIndex); + bool isBullishTrendExhaustedPOI = isTrendExhaustedPOI && + IsXBullish(dir); + bool isBearishTrendExhaustedPOI = isTrendExhaustedPOI && + IsXBearish(dir); + if (isTrendExhaustedPOI) + { + // + Print("isTrendExhaustedPOI: ", ToXString(dir)); + DebugBreak(); + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * Trend‑following: + * - Requires KI Fast + KI Slow alignment. + * - Confirms with MA crossover. + * - RSI filter to avoid false signals. + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL & bar, + XBoxZone & zone, + XTarget & targets[], + ENUM_X_DIRECTION & dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + bool isBullish = kiParser.IsBullishMomentumTrend(bar.Index()); + bool isBearish = kiParser.IsBearishMomentumTrend(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_MOMENTUM); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Breakout: + * - Detects price breaking KI bands with ATR confirmation. + * - Confirms with Momentum Bar pattern. + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL & bar, + XBoxZone & zone, + XTarget & targets[], + ENUM_X_DIRECTION & dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = poiDetector.IsBullishBreakoutPOI(bar.Index()); + bool isBearish = poiDetector.IsBearishBreakoutPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_TRUE_GAPED); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Exhaustion: + * - Strong trend + RSI extreme + volatility low. + * - Confirms with Piercing/Dark Cloud Cover candlestick. + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL & bar, + XBoxZone & zone, + XTarget & targets[], + ENUM_X_DIRECTION & dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = poiDetector.IsBullishTrendExhaustedPOI(bar.Index()); + bool isBearish = poiDetector.IsBearishTrendExhaustedPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_PIERCING); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 5 ... + * + * Continuation: + * - Requires strong trend confirmation (KI fast/slow + MA crossover + RSI filter). + * - Confirms with continuation candlestick patterns (Flag or Rising pattern). + * - Ensures zone validity for entry. + * + * @return ( bool ) + */ + bool Strategy5HasSignal( + XOHCL & bar, + XBoxZone & zone, + XTarget & targets[], + ENUM_X_DIRECTION & dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = kiParser.IsTrendStrongBullish(bar.Index()); + bool isBearish = kiParser.IsTrendStrongBearish(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Confirm Direction by Candlestick Continuation Patterns ... + isBullish = + isBullish && + poiDetector.IsBullishContinuationPOI(bar.Index()); + isBearish = + isBearish && + poiDetector.IsBearishContinuationPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_PIERCING); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /// + // + // + /// + + result = + isBullish + ? // entry > iBar.low && + entry < iBar.high + // && + // iBar.GetLowShadow() > iBar.GetHighShadow() + : // entry < iBar.high && + entry > iBar.low + // && + // iBar.GetHighShadow() > iBar.GetLowShadow() + ; + + /// + /// + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL & bar, + XBoxZone & zone, + XTarget & targets[], + ENUM_X_DIRECTION & dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = IsBullishPOILongEntry(barIndex); + bool isBearish = IsBearishPOIShortEntry(barIndex); + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Validate near Support / Resistance Zones ... + bool validateNearSupRes = true; + if (result && validateNearSupRes) + { + // + // Configs ... + int loopback = 100; + int validationLength = 7; + double nearThreshold = 5; + int validationRetests = 0; + int validationLoopback = 100; + double validationThreshold = 5; + + // + // Filling Zones ... + XBoxZone zones[]; + if (isBullish) + { + // + // Detect Supports ... + poiDetector.DetectSupports( + zones, + barIndex, + loopback, + true, + validationLength, // Validation Length ... + validationRetests, // Min Retest ... + validationThreshold, // Retest Threshold ... + validationLoopback, // Retest Loopback ... + symbol, + period // + ); + } + else if (isBearish) + { + // + // Detect Resistances ... + poiDetector.DetectResistances( + zones, + barIndex, + loopback, + true, + validationLength, // Validation Length ... + validationRetests, // Min Retest ... + validationThreshold, // Retest Threshold ... + validationLoopback, // Retest Loopback ... + symbol, + period // + ); + } + + // + if (HasChild(zones)) + { + // + XPOIDrawConfig iConfig; + iConfig.Default(); + + // + poiDrawer.DrawZones(zones, iConfig); + iConfig.Clean(); + DebugBreak(); + } + + // + // Check Has Nearest ... + int nearIDX = -1; + result = poiDetector.HasNearZone( + nearIDX, + bar.close, + nearThreshold, + zones // + ); + + // + // Validate ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate by ATR Rising/Falling ... + bool validateByATRRaisFalling = false; + if (result && validateByATRRaisFalling) + { + // + // Bullish: + // - ATR Lower Rising ... + // - ATR Over ATR Ma ... + // Bearsih: + // - ATR Upper Falling ... + // - ATR Over ATR Ma ... + + // + isBullish = + isBullish && + // kiHelper.GetATR(barIndex) > kiHelper.GetATRSmoothed(barIndex) && + kiHelper.GetKILower(barIndex) > kiHelper.GetKILower(barIndex + 1); + isBearish = + isBearish && + // kiHelper.GetATR(barIndex) > kiHelper.GetATRSmoothed(barIndex) && + kiHelper.GetKIUpper(barIndex) < kiHelper.GetKIUpper(barIndex + 1); + result = isBullish || isBearish; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate by RSI ... + bool validatebyRSI = false; + if (result && validatebyRSI) + { + // + // Bullish: + // - Not in Over Baught; + // - Rising; + // Bearish : + // - Not in Over Sold; + // - Falling; + + // + isBullish = + isBullish && + !kiParser.IsRSIOverbought(barIndex) && + kiHelper.GetRSI(barIndex) > kiHelper.GetRSI(barIndex + 1); + isBearish = + isBearish && + !kiParser.IsRSIOversold(barIndex) && + kiHelper.GetRSI(barIndex) < kiHelper.GetRSI(barIndex + 1); + result = isBullish || isBearish; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate by iBar Pattern ... + // in this Strategy we have PinBar or SignalKeyBar ... + bool validateByBarPatterns = false; + if (result && validateByBarPatterns) + { + // + // Pin ... + bool isPinBar = poiDetector.IsPinnedBar( + iBar, + dir // + ); + bool isPinBarBullish = + isPinBar && + IsXBullish(dir); + bool isPinBarBearish = + isPinBar && + IsXBearish(dir); + + // + // Engulfe ... + bool isEngulfed = poiDetector.IsEngulfedBar( + iBar, + dir // + ); + bool isEngulfedBullish = + isEngulfed && + IsXBullish(dir); + bool isEngulfedBearish = + isEngulfed && + IsXBearish(dir); + + // + // Signal Key Bar ... + bool isSignalKeyBar = poiDetector.IsSignalKeyBarPattern( + iBar, + dir // + ); + bool isSignalKeyBarBullish = + isSignalKeyBar && + IsXBullish(dir); + bool isSignalKeyBarBearish = + isSignalKeyBar && + IsXBearish(dir); + + // + isBullish = + isBullish && + (isEngulfedBullish); + isBearish = + isBearish && + (isEngulfedBearish); + + // // + // isBullish = + // isBullish && + // (isPinBarBullish || + // isEngulfedBullish || + // isSignalKeyBarBullish); + // isBearish = + // isBearish && + // (isPinBarBearish || + // isEngulfedBearish || + // isSignalKeyBarBearish); + + // + result = isBullish || isBearish; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + if (result) + { + // + double upper = isBullish + ? entry + : iBar.high; + double lower = isBullish + ? iBar.low + : entry; + datetime to = bar.time; + datetime from = iBar.BeforeOn(); + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + if (result) + { + // + XPOIDrawConfig iConfig; + iConfig.Default(); + + // + poiDrawer.DrawZone(zone, iConfig); + + // + // DebugBreak(); + } + } + + // + iBar.Clean(); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL & bar, + XBoxZone & zone, + XTarget & targets[], + ENUM_X_DIRECTION & dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = IsBullishPOILongEntry(barIndex); + bool isBearish = IsBearishPOIShortEntry(barIndex); + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Validate near Support / Resistance Zones ... + bool validateNearSupRes = true; + if (result && validateNearSupRes) + { + // + // Configs ... + int loopback = 100; + int validationLength = 7; + double nearThreshold = 5; + int validationRetests = 0; + int validationLoopback = 100; + double validationThreshold = 5; + + // + // Filling Zones ... + XBoxZone zones[]; + if (isBullish) + { + // + // Detect Supports ... + poiDetector.DetectSupports( + zones, + barIndex, + loopback, + true, + validationLength, // Validation Length ... + validationRetests, // Min Retest ... + validationThreshold, // Retest Threshold ... + validationLoopback, // Retest Loopback ... + symbol, + period // + ); + } + else if (isBearish) + { + // + // Detect Resistances ... + poiDetector.DetectResistances( + zones, + barIndex, + loopback, + true, + validationLength, // Validation Length ... + validationRetests, // Min Retest ... + validationThreshold, // Retest Threshold ... + validationLoopback, // Retest Loopback ... + symbol, + period // + ); + } + + // + if (HasChild(zones)) + { + // + XPOIDrawConfig iConfig; + iConfig.Default(); + + // + poiDrawer.DrawZones(zones, iConfig); + iConfig.Clean(); + // DebugBreak(); + } + + // + // Check Has Nearest ... + int nearIDX = -1; + result = poiDetector.HasNearZone( + nearIDX, + bar.close, + nearThreshold, + zones // + ); + + // + // Validate ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate by ATR Rising/Falling ... + bool validateByATRRaisFalling = true; + if (result && validateByATRRaisFalling) + { + // + // Bullish: + // - ATR Lower Rising ... + // - ATR Over ATR Ma ... + // Bearsih: + // - ATR Upper Falling ... + // - ATR Over ATR Ma ... + + // + isBullish = + isBullish && + // kiHelper.GetATR(barIndex) > kiHelper.GetATRSmoothed(barIndex) && + kiHelper.GetKILower(barIndex) > kiHelper.GetKILower(barIndex + 1); + isBearish = + isBearish && + // kiHelper.GetATR(barIndex) > kiHelper.GetATRSmoothed(barIndex) && + kiHelper.GetKIUpper(barIndex) < kiHelper.GetKIUpper(barIndex + 1); + result = isBullish || isBearish; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate by RSI ... + bool validatebyRSI = false; + if (result && validatebyRSI) + { + // + // Bullish: + // - Not in Over Baught; + // - Rising; + // Bearish : + // - Not in Over Sold; + // - Falling; + + // + isBullish = + isBullish && + !kiParser.IsRSIOverbought(barIndex) && + kiHelper.GetRSI(barIndex) > kiHelper.GetRSI(barIndex + 1); + isBearish = + isBearish && + !kiParser.IsRSIOversold(barIndex) && + kiHelper.GetRSI(barIndex) < kiHelper.GetRSI(barIndex + 1); + result = isBullish || isBearish; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate by iBar Pattern ... + // in this Strategy we have PinBar or SignalKeyBar ... + bool validateByBarPatterns = false; + if (result && validateByBarPatterns) + { + // + // Pin ... + bool isPinBar = poiDetector.IsPinnedBar( + iBar, + dir // + ); + bool isPinBarBullish = + isPinBar && + IsXBullish(dir); + bool isPinBarBearish = + isPinBar && + IsXBearish(dir); + + // + // Engulfe ... + bool isEngulfed = poiDetector.IsEngulfedBar( + iBar, + dir // + ); + bool isEngulfedBullish = + isEngulfed && + IsXBullish(dir); + bool isEngulfedBearish = + isEngulfed && + IsXBearish(dir); + + // + // Signal Key Bar ... + bool isSignalKeyBar = poiDetector.IsSignalKeyBarPattern( + iBar, + dir // + ); + bool isSignalKeyBarBullish = + isSignalKeyBar && + IsXBullish(dir); + bool isSignalKeyBarBearish = + isSignalKeyBar && + IsXBearish(dir); + + // + isBullish = + isBullish && + (isEngulfedBullish); + isBearish = + isBearish && + (isEngulfedBearish); + + // // + // isBullish = + // isBullish && + // (isPinBarBullish || + // isEngulfedBullish || + // isSignalKeyBarBullish); + // isBearish = + // isBearish && + // (isPinBarBearish || + // isEngulfedBearish || + // isSignalKeyBarBearish); + + // + result = isBullish || isBearish; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + if (result) + { + // + double upper = isBullish + ? entry + : iBar.high; + double lower = isBullish + ? iBar.low + : entry; + datetime to = bar.time; + datetime from = iBar.BeforeOn(); + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + if (result) + { + // + XPOIDrawConfig iConfig; + iConfig.Default(); + + // + poiDrawer.DrawZone(zone, iConfig); + + // + // DebugBreak(); + } + } + + // + iBar.Clean(); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + // // + // isBullish = + // // majorSupport.IsValid() && + // minorSupport.IsValid() && + // poiDetector.IsKIBullishPOI(barIndex) && + // poiDetector.HasCandlestickDirection( + // iBar, + // X_DIRECTION_BULLISH // + // ) && + // IsTFBullishPattern(barIndex, PERIOD_M5) && + // // minorSupport.lower <= majorSupport.upper && + // poiDetector.IsNearZone(iBar.close, minorSupport, 10); + + // // + // isBearish = + // // majorResistance.IsValid() && + // minorResistance.IsValid() && + // poiDetector.IsKIBearishPOI(barIndex) && + // poiDetector.HasCandlestickDirection( + // iBar, + // X_DIRECTION_BEARISH // + // ) && + // IsTFBearishPattern(barIndex, PERIOD_M5) && + // // minorResistance.upper >= majorResistance.lower && + // poiDetector.IsNearZone(iBar.close, minorResistance, 10); + + // + // Retrieve Base Conditions ... + // isBullish = + // isBullish && + // IsBullishPOILongEntry(barIndex); + // isBearish = + // isBearish && + // IsBearishPOIShortEntry(barIndex); + + // // + // // Do Validation and Filtering Market Structure if required ... + + // // + // // Validate near Support / Resistance Zones ... + // bool validateNearSupRes = true; + // if (result && validateNearSupRes) + // { + // // + // // Configs ... + // int loopback = 100; + // int validationLength = 7; + // double nearThreshold = 5; + // int validationRetests = 0; + // int validationLoopback = 100; + // double validationThreshold = 5; + + // // + // // Filling Zones ... + // XBoxZone zones[]; + // if (isBullish) + // { + // // + // // Detect Supports ... + // poiDetector.DetectSupports( + // zones, + // barIndex, + // loopback, + // true, + // validationLength, // Validation Length ... + // validationRetests, // Min Retest ... + // validationThreshold, // Retest Threshold ... + // validationLoopback, // Retest Loopback ... + // symbol, + // period // + // ); + // } + // else if (isBearish) + // { + // // + // // Detect Resistances ... + // poiDetector.DetectResistances( + // zones, + // barIndex, + // loopback, + // true, + // validationLength, // Validation Length ... + // validationRetests, // Min Retest ... + // validationThreshold, // Retest Threshold ... + // validationLoopback, // Retest Loopback ... + // symbol, + // period // + // ); + // } + + // // + // if (HasChild(zones)) + // { + // // + // XPOIDrawConfig iConfig; + // iConfig.Default(); + + // // + // poiDrawer.DrawZones(zones, iConfig); + // iConfig.Clean(); + // // DebugBreak(); + // } + + // // + // // Check Has Nearest ... + // int nearIDX = -1; + // result = poiDetector.HasNearZone( + // nearIDX, + // bar.close, + // nearThreshold, + // zones // + // ); + + // // + // // Validate ... + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + // } + + // // + // // Validate by ATR Rising/Falling ... + // bool validateByATRRaisFalling = true; + // if (result && validateByATRRaisFalling) + // { + // // + // // Bullish: + // // - ATR Lower Rising ... + // // - ATR Over ATR Ma ... + // // Bearsih: + // // - ATR Upper Falling ... + // // - ATR Over ATR Ma ... + + // // + // isBullish = + // isBullish && + // // kiHelper.GetATR(barIndex) > kiHelper.GetATRSmoothed(barIndex) && + // kiHelper.GetKILower(barIndex) > kiHelper.GetKILower(barIndex + 1); + // isBearish = + // isBearish && + // // kiHelper.GetATR(barIndex) > kiHelper.GetATRSmoothed(barIndex) && + // kiHelper.GetKIUpper(barIndex) < kiHelper.GetKIUpper(barIndex + 1); + // result = isBullish || isBearish; + + // // + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + // } + + // // + // // Validate by RSI ... + // bool validatebyRSI = false; + // if (result && validatebyRSI) + // { + // // + // // Bullish: + // // - Not in Over Baught; + // // - Rising; + // // Bearish : + // // - Not in Over Sold; + // // - Falling; + + // // + // isBullish = + // isBullish && + // !kiParser.IsRSIOverbought(barIndex) && + // kiHelper.GetRSI(barIndex) > kiHelper.GetRSI(barIndex + 1); + // isBearish = + // isBearish && + // !kiParser.IsRSIOversold(barIndex) && + // kiHelper.GetRSI(barIndex) < kiHelper.GetRSI(barIndex + 1); + // result = isBullish || isBearish; + + // // + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + // } + + // // + // // Validate by iBar Pattern ... + // // in this Strategy we have PinBar or SignalKeyBar ... + // bool validateByBarPatterns = false; + // if (result && validateByBarPatterns) + // { + // // + // // Pin ... + // bool isPinBar = poiDetector.IsPinnedBar( + // iBar, + // dir // + // ); + // bool isPinBarBullish = + // isPinBar && + // IsXBullish(dir); + // bool isPinBarBearish = + // isPinBar && + // IsXBearish(dir); + + // // + // // Engulfe ... + // bool isEngulfed = poiDetector.IsEngulfedBar( + // iBar, + // dir // + // ); + // bool isEngulfedBullish = + // isEngulfed && + // IsXBullish(dir); + // bool isEngulfedBearish = + // isEngulfed && + // IsXBearish(dir); + + // // + // // Signal Key Bar ... + // bool isSignalKeyBar = poiDetector.IsSignalKeyBarPattern( + // iBar, + // dir // + // ); + // bool isSignalKeyBarBullish = + // isSignalKeyBar && + // IsXBullish(dir); + // bool isSignalKeyBarBearish = + // isSignalKeyBar && + // IsXBearish(dir); + + // // + // isBullish = + // isBullish && + // (isEngulfedBullish); + // isBearish = + // isBearish && + // (isEngulfedBearish); + + // // // + // // isBullish = + // // isBullish && + // // (isPinBarBullish || + // // isEngulfedBullish || + // // isSignalKeyBarBullish); + // // isBearish = + // // isBearish && + // // (isPinBarBearish || + // // isEngulfedBearish || + // // isSignalKeyBarBearish); + + // // + // result = isBullish || isBearish; + + // // + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + // } + + // + // Recent Support ... + // else if (HasChild(supports)) + // { + // // + // tmpSupportIDX = GetYoungestBelow(iBar.close, supports); + // if (IsValidIndex(tmpSupportIDX)) + // { + // zone = supports[tmpSupportIDX]; + // } + // } + + // + // Recent Resistance ... + // else if (HasChild(resistances)) + // { + // // + // tmpResistanceIDX = GetYoungestAbove(iBar.close, resistances); + // if (IsValidIndex(tmpResistanceIDX)) + // { + // zone = resistances[tmpResistanceIDX]; + // } + // } + + // + // + // + + // #region Market Structure ... + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone minorSupport; + XBoxZone majorSupport; + XBoxZone minorResistance; + XBoxZone majorResistance; + poiDetector.GetCurrentStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + barIndex, + bar.symbol, + iBar.period, // Minor ... + PERIOD_H1, // Major ... + 50, + 14, + 21, + 0 // + ); + + // + // Refining Zones ... + int refineLoopback = 500; + double refineBreakThreshold = 10; + ENUM_X_PRICE refineBreakBy = X_PRICE_CLOSE; + poiDetector.RefineStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + refineLoopback, + refineBreakThreshold, + refineBreakBy // + ); + // #endregion + + // #region NearInside Support/Resistance ... + // + int tmpSupportIDX = -1; + bool isNearSupport = poiDetector.HasNearZone(tmpSupportIDX, iBar.close, 5, supports); + if (isNearSupport) + { + scoreBullish++; + } + + // + int tmpResistanceIDX = -1; + bool isNearResistance = poiDetector.HasNearZone(tmpResistanceIDX, iBar.close, 5, resistances); + if (isNearResistance) + { + scoreBearish++; + } + // #endregion + + // + // Cleanup Resources ... + iBar.Clean(); + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + // Draws ... + bool draw = true; + if (draw && result) + { + // + int drawn = 0; + + // + XPOIDrawConfig config; + config.Default(); + + // + if (zone.IsValid()) + { + // + drawn++; + + // + config.zonesWidth = 3; + config.bullishColor = clrYellow; + config.bearishColor = clrOrange; + + // + poiDrawer.DrawZone(zone, config); + + // + config.Default(); + } + + // + // Minors ... + if (minorSupport.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(minorSupport, config); + } + if (minorResistance.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(minorResistance, config); + } + + // + // Majors ... + config.bullishColor = clrLime; + config.bearishColor = clrRed; + config.zonesWidth = 4; + + // + if (majorSupport.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(majorSupport, config); + } + if (majorResistance.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(majorResistance, config); + } + + // + config.Clean(); + + // + if (drawn > 0) + { + DebugBreak(); + } + } \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/X121XKI/x-saherelm.x121.xki.ea.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/x-saherelm.x121.xki.ea.mq5 new file mode 100644 index 0000000..b2c6c93 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/X121XKI/x-saherelm.x121.xki.ea.mq5 @@ -0,0 +1,33 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121XKIEA +// Description: Base Expert Advisor as Template ... +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#property description "SaherElm XFIMA Expert Advisor" +#property strict + +// +#define ShortName "X121XKIEA" + +// +// Importts ... +#include "../X121XKIEA/Classes/x-saherelm.x121xki.expert.class.mq5" + +// +// Inputs ... + +//#region Inputs ... +//#endregion \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/X121XKI/x-saherelm.x121xki.expert.class.mq5 b/BKPS/14041018/Documents/BKP/X121XKI/x-saherelm.x121xki.expert.class.mq5 new file mode 100644 index 0000000..e69de29 diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/1.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/1.mq5 new file mode 100644 index 0000000..4dd6293 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/1.mq5 @@ -0,0 +1,1195 @@ + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validator Flags ... + bool validateByATRZone = false; + bool validateByBarPatterns = false; + bool validateRejectedXFIMA = true; + bool validateByAffectedZone = false; + bool validateStartedPullback = true; + bool validateStartedPinnedBar = true; + bool validateByPinBarZoneTrend = false; + bool validateByDirectionalZones = false; + bool validateByDoubleBarPatterns = false; + bool validateByCycleMAsDirection = true; + bool validateByInDirectionalZones = false; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XBoxZone atrBox; + XBoxZone mcPVZone; + XBoxZone lcPVZone; + XBoxZone hcPVZone; + double rejecteds[]; + XBoxZone supports[]; + XBoxZone pinBarZone; + XBoxZone pullbackZone; + XBoxZone affectedZone; + XBoxZone liquidityZone; + XBoxZone resistances[]; + XTrend pinBarZoneTrend; + bool isBullish = false; + bool isBearish = false; + XPatternAnalysis iPatterns; + XPatternAnalysis iPPatterns; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysis p3BarPatterns; + ENUM_X_BAR_PATTERN doublePatterns[]; + XPatternAnalysisConfig iPatternsConfig; + + // + // Reading Bars ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading Bar Patterns ... + iPatternsConfig.Default(); + iPatternsConfig.FullPattern(); + result = + result && + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p3Bar, + p3BarPatterns, + iPatternsConfig // + ); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } + + // + // Detect Support / Resistance / FVG Touches ... + + + // + // Prepare Zone ... + if (result) + { + // + string type = NULL; + datetime to = NULL; + datetime from = NULL; + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + ENUM_X_DIRECTION zDir = X_DIRECTION_NONE; + + // + zone.at = bar.time; + zone.symbol = bar.symbol; + zone.period = bar.period; + + // + if (pinBarZone.IsValid()) + { + // + upper = + !NotEmptyZero(upper) + ? pinBarZone.upper + : MathMax(upper, pinBarZone.upper); + + // + lower = + !NotEmptyZero(lower) + ? pinBarZone.lower + : MathMin(lower, pinBarZone.lower); + + // + to = bar.time; + from = !IsXValid(from) + ? pinBarZone.from + : MathMin(from, pinBarZone.from); + + // + zDir = pinBarZone.dir; + type = pinBarZone.type; + } + + // + if (pullbackZone.IsValid()) + { + // + upper = + !NotEmptyZero(upper) + ? pullbackZone.upper + : MathMax(upper, pullbackZone.upper); + + // + lower = + !NotEmptyZero(lower) + ? pullbackZone.lower + : MathMin(lower, pullbackZone.lower); + + // + from = !IsXValid(from) + ? pullbackZone.from + : MathMin(from, pullbackZone.from); + + // + if (!HasDirection(zDir)) + { + zDir = pullbackZone.dir; + } + + // + type = + !IsXValid(type) + ? pullbackZone.type + : type + "_" + pullbackZone.type; + } + + // + zone.to = to; + zone.dir = zDir; + zone.from = from; + zone.type = type; + zone.upper = upper; + zone.lower = lower; + + // + result = zone.IsValid(); + if (result) + { + // + int zoneLength = zone.FromIndex() - zone.ToIndex(); + double zoneLL = pBar.FindLowest(zoneLength, MODE_LOW); + double zoneHH = pBar.FindHighest(zoneLength, MODE_HIGH); + + // + if (zone.IsBullish()) + { + zone.lower = MathMin(zone.lower, zoneLL); + } + if (zone.IsBearish()) + { + zone.upper = MathMax(zone.upper, zoneHH); + } + } + + // + // Validating Zone by Shadows ... + if (result) + { + // + XOHCL iBar; + int idx = -1; + bool canContinue = true; + while (canContinue) + { + // + idx = zone.FromIndex() + 1; + canContinue = IsValidIndex(idx); + if (!canContinue) + { + break; + } + + // + iBar.Clean(); + canContinue = pBar.BarAt(idx, iBar); + if (!canContinue) + { + break; + } + + // + canContinue = isBullish + ? iBar.low > zone.lower + : iBar.high < zone.upper; + if (!canContinue) + { + break; + } + + // + zone.from = iBar.time; + } + } + + // + if (!result) + { + // + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Validate Bu Liquidity ... + if (result) + { + // + // Detecting Liquidity ... + XOHCL liqBar; + int idx = zone.FromIndex() + 1; + result = IsValidIndex(idx); + result = result && + bar.BarAt(idx, liqBar); + if (result) + { + // + liquidityZone = zone; + + // + if (isBullish) + { + // + liquidityZone.upper = liquidityZone.lower; + liquidityZone.lower = liqBar.low; + } + else if (isBearish) + { + // + liquidityZone.lower = liquidityZone.upper; + liquidityZone.upper = liqBar.high; + } + } + + // + liqBar.Clean(); + result = liquidityZone.IsValid(); + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Validate By Affected Zone ... + if (result && validateByAffectedZone) + { + // + // Check pBar is Reject Zone ... + + // // + // // Prepare Zone ... + + // // + // XOHCL tmpBar; + // XBoxZone tmpZone; + + // // + // isBullish = + // isBullish && + // poiDetector.IsSupportTouched( + // p2Bar, + // tmpBar, + // tmpZone, + // 5, + // 21 // + // ); + // if (isBullish) + // { + // affectedZone = tmpZone; + // } + + // // + // isBearish = + // isBearish && + // poiDetector.IsResistanceTouched( + // p2Bar, + // tmpBar, + // tmpZone, + // 5, + // 21 // + // ); + // if (isBearish) + // { + // affectedZone = tmpZone; + // } + + // // + // tmpBar.Clean(); + // tmpZone.Clean(); + + // // + // result = isBullish || isBearish; + } + + // + if (result) + { + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawZone(liquidityZone, structureDrawConfig.drawConfig); + DebugBreak(); + } + + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + + // + // Looking For a Pin Bar in P2Bar ... + bool isP2BarIsPinBar = poiDetector.IsPinnedBar( + p2Bar, + dir, + 4, // Shadow Multiplier ... + 4, // Minimum Range Multiplier ... + true // Force Pin Bar Direction ... + ); + if (isP2BarIsPinBar) + { + // + isP2BarIsPinBar = ToBox( + p2Bar, + pinBarZone, + dir, + X_BAR_PATTERN_PINNED // + ); + if (isP2BarIsPinBar) + { + // + pinBarZone.to = bar.time; + + // + // Validate By PinBar Zone Trend ... + if (validateByPinBarZoneTrend) + { + // + isP2BarIsPinBar = poiDetector.HasBoundaryTrend( + pinBarZone, + pinBarZoneTrend, + false // + ); + + // + isP2BarIsPinBar = + isP2BarIsPinBar && + dir == pinBarZoneTrend.dir; + } + + // + // Validate PinBar Zone By XFIMA ... + if (validateRejectedXFIMA) + { + // + int rejectedsCount = poiDetector.IsRejectXFIMA(p2Bar, rejecteds, pinBarZone.dir); + isP2BarIsPinBar = IsValidSize(rejectedsCount); + } + } + } + bool isP2BarPinnedBullish = isP2BarIsPinBar && IsXBullish(dir); + bool isP2BarPinnedBearish = isP2BarIsPinBar && IsXBearish(dir); + + // + // Check P2Bar is Pullback Bar ... + bool isPBarIsPullBack = poiDetector.IsPullbackPattern( + pBar, + pullbackZone, + dir, + 2, // Pull back Length ... + false // Force Break Pullback ... + ); + bool isPBarPullbackBullish = isPBarIsPullBack && pullbackZone.IsBullish(); + bool isPBarPullbackBaerish = isPBarIsPullBack && pullbackZone.IsBearish(); + if (isPBarIsPullBack && validateRejectedXFIMA) + { + // + double iRejecteds[]; + int rejectedCounts = poiDetector.IsRejectXFIMA( + p2Bar, + iRejecteds, + dir, + X_PRICE_CLOSE, + X_PRICE_OPEN, + X_PRICE_OPEN, + X_PRICE_CLOSE, + false // + ); + isPBarIsPullBack = IsValidSize(rejectedCounts); + if (isPBarIsPullBack) + { + // + Copy( + iRejecteds, + rejecteds, + false // + ); + } + } + + // + isBullish = + isP2BarPinnedBullish || + isPBarPullbackBullish; + + // + isBearish = + isP2BarPinnedBearish || + isPBarPullbackBullish; + + // + result = isBullish || isBearish; + + // + // Validate Starter Pinned ... + if (result && validateStartedPinnedBar && !validateStartedPullback) + { + // + isBullish = + isBullish && + isP2BarPinnedBullish; + + // + isBearish = + isBearish && + isP2BarPinnedBearish; + + // + result = isBullish || isBearish; + } + + // + // Validate Starter Pullback ... + if (result && !validateStartedPinnedBar && validateStartedPullback) + { + // + isBullish = + isBullish && + isPBarPullbackBullish; + + // + isBearish = + isBearish && + isPBarPullbackBaerish; + + // + result = isBullish || isBearish; + } + + // + // Validate By ATR Zone ... + if (result && validateByATRZone) + { + // + // Checking ATR Box ... + bool hasATRBox = fimaParser.GetATRBox( + atrBox, + bar.Index() // + ); + bool hasATRBoxBullish = hasATRBox && atrBox.IsBullish(); + bool hasATRBoxBearish = hasATRBox && atrBox.IsBearish(); + + // + isBullish = + isBullish && + hasATRBoxBullish; + + // + isBearish = + isBearish && + hasATRBoxBearish; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Detect Directional Candlestic Patterns ... + if (result && validateByBarPatterns) + { + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isP2BarHasBullishPatterns = + (bar.close > p2Bar.low || + bar.open > p2Bar.low) && + ( + // + p2BarPatterns.IsPinned(X_DIRECTION_BULLISH) || + p2BarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + p2BarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + p2BarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + p2BarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isP3BarHasBullishPatterns = + (bar.close > p3Bar.low || + bar.open > p3Bar.low) && + ( + // + p3BarPatterns.IsPinned(X_DIRECTION_BULLISH) || + p3BarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + p3BarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + p3BarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + p3BarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + bool isP2BarHasBearishPatterns = + (bar.close < p2Bar.high || + bar.open < p2Bar.high) && + ( + // + p2BarPatterns.IsPinned(X_DIRECTION_BEARISH) || + p2BarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + p2BarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + p2BarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + p2BarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + bool isP3BarHasBearishPatterns = + (bar.close < p3Bar.high || + bar.open < p3Bar.high) && + ( + // + p3BarPatterns.IsPinned(X_DIRECTION_BEARISH) || + p3BarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + p3BarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + p3BarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + p3BarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + bool hasBullishPatterns = + isPBarHasBullishPatterns && + (isP2BarHasBullishPatterns || + isP3BarHasBullishPatterns); + + // + bool hasBearishPatterns = + isPBarHasBearishPatterns && + (isP2BarHasBearishPatterns || + isP3BarHasBearishPatterns); + + // + isBullish = + isBullish && + hasBullishPatterns; + + // + isBearish = + isBearish && + hasBearishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validating Market Direction ... + if (result && validateByCycleMAsDirection) + { + // + // Bullish ... + bool isLCBullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCBullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isLCHigherLow = + (fimaParser.IsLCHigherLow(pBar.Index()) || + fimaParser.IsLCHigherLow(p2Bar.Index()) || + fimaParser.IsLCHigherLow(p3Bar.Index())); + bool isCyclesBullish = + isLCBullish && + isHCBullish && + isLCHigherLow; + + // + // Bearish ... + bool isLCBearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCBearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isLCLowerHigh = + (fimaParser.IsLCLowerHigh(pBar.Index()) || + fimaParser.IsLCLowerHigh(p2Bar.Index()) || + fimaParser.IsLCLowerHigh(p3Bar.Index())); + bool isCyclesBearish = + isLCBearish && + isHCBearish && + isLCLowerHigh; + + // + isBullish = + isBullish && + isCyclesBullish; + + // + isBearish = + isBearish && + isCyclesBearish; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate By Double Bar Patterns ... + if (result && validateByDoubleBarPatterns) + { + // + GetCandlestickPatterns(doublePatterns); + bool hasDoublePatterns = poiDetector.HasDoublePatterns( + pBar, + dir, + iPatterns, + iPPatterns, + doublePatterns, + iPatternsConfig, + 5 // + ); + bool hasBullishDoublePatterns = hasDoublePatterns && IsXBullish(dir); + bool hasBearishDoublePatterns = hasDoublePatterns && IsXBearish(dir); + + // + isBullish = + isBullish && + hasBullishDoublePatterns; + + // + isBearish = + isBearish && + hasBearishDoublePatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Directional Zones ... + if (result && validateByDirectionalZones) + { + // + // Collecting Zones ... + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone tmpZone; + + // + // Support ... + bool hasSupport = pBarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = pBarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = p2BarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = p3BarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = p3BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = HasChild(supports); + + // + // Resistance ... + bool hasResistance = pBarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = pBarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = p2BarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = p3BarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = p3BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = HasChild(resistances); + + // + // Cleanup ... + tmpBar.Clean(); + tmpZone.Clean(); + tmpPivot.Clean(); + + // + // Validating ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by InDirectional Zones ... + if (result && validateByInDirectionalZones) + { + // + // Collecting Zones ... + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone tmpZone; + + // + // Supports ... + bool hasSupport = false; + if (!HasChild(supports)) + { + // + hasSupport = pBarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = pBarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = p2BarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = p3BarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = p3BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = HasChild(supports); + } + hasSupport = HasChild(supports); + + // + // Resistances ... + bool hasResistance = false; + if (!HasChild(resistances)) + { + // + hasResistance = pBarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = pBarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = p2BarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = p3BarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = p3BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = HasChild(resistances); + } + hasResistance = HasChild(resistances); + + // + // Cleanup ... + tmpBar.Clean(); + tmpZone.Clean(); + tmpPivot.Clean(); + + // + // Validate by Not InDirectional Exixsts ... + result = + (isBullish && !hasResistance) || + (isBearish && !hasSupport); + + // + // Validate InDirectional Distance by TP ... + if (!result) + { + // + // Calculate Requirements ... + double points = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, (isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH)); + double slAddition = slAdditionDistance <= 0 ? 0 : slAdditionDistance * points; + double sl = isBullish + ? pinBarZone.lower - slAddition + : pinBarZone.upper + slAddition; + double risk = MathAbs(entry - sl); + double tpReward = defaultSignalR2R * risk; + double tp = isBullish + ? entry + tpReward + : entry - tpReward; + + // + int idx = -1; + if (isBullish) + { + idx = GetYoungest(resistances); + } + else if (isBearish) + { + idx = GetYoungest(supports); + } + result = IsValidIndex(idx); + result = + result && + (isBullish + ? tp < resistances[idx].lower + : tp > supports[idx].upper); + } + + // + // Reset Flags ... + if (!result) + { + // + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Detecting Direction ... + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + // Since Zone Prepared in Above Steps ... + // here we only Validate it ... + result = zone.IsValid(); + } + + // + // Draws ... + if (result) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + XPatternAnalysisDrawConfig iPatternsConfig = structureDrawConfig.barAnalysisDrawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + // PinBar Zone ... + if (pinBarZone.IsValid()) + { + poiDrawer.DrawZone(pinBarZone, iConfig); + } + + // + // Pullback Zone ... + if (pullbackZone.IsValid()) + { + poiDrawer.DrawZone(pullbackZone, iConfig); + } + + // + // PinBar Zone Trend ... + if (pinBarZoneTrend.IsValid()) + { + poiDrawer.DrawTrendLine(pinBarZoneTrend, iConfig); + } + + // + // Rejected Values ... + if (HasChild(rejecteds)) + { + // + XTrend iTrend; + bool has = false; + int count = ArraySize(rejecteds); + datetime toTime = zone.to + PeriodSeconds(zone.period); + datetime fromTime = zone.to - PeriodSeconds(zone.period); + for (int i = 0; i < count; i++) + { + // + // Initialize Trend ... + iTrend.Clean(); + has = iTrend.Init( + bar.symbol, + bar.period, + bar.time, + rejecteds[i], + fromTime, + rejecteds[i], + toTime // + ); + if (has) + { + poiDrawer.DrawTrendLine(iTrend, iConfig); + } + } + } + + // + // Draw Zone ... + if (zone.IsValid()) + { + // + iConfig.zonesStyle = STYLE_DASHDOT; + iConfig.bullishColor = clrYellow; + iConfig.bearishColor = clrDarkOrange; + + // + poiDrawer.DrawZone(zone, iConfig); + } + + // + // poiDrawer.DrawZone(mcPVZone, iConfig); + // poiDrawer.DrawZone(lcPVZone, iConfig); + // poiDrawer.DrawZone(hcPVZone, iConfig); + + // + // poiDrawer.DrawZone(pinBarZone, iConfig); + // poiDrawer.DrawZone(pullbackZone, iConfig); + // poiDrawer.DrawTrendLine(pinBarZoneTrend, iConfig); + + // + poiDrawer.DrawPatternAnalysis(pBarPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(p2BarPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(p3BarPatterns, iPatternsConfig); + + // + // if (hasATRBox) + // { + // poiDrawer.DrawZone(atrBox, iConfig); + // } + + // + // if (hasDoublePatterns) + // { + // // + // poiDrawer.DrawPatternAnalysis(iPatterns, iPatternsConfig); + // poiDrawer.DrawPatternAnalysis(iPPatterns, iPatternsConfig); + // } + + // + iConfig.Clean(); + iPatternsConfig.Clean(); + + // + DebugBreak(); + + // // + // result = false; + // isBullish = false; + // isBearish = false; + // zone.Clean(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(supports); + mcPVZone.Clean(); + lcPVZone.Clean(); + hcPVZone.Clean(); + XClean(rejecteds); + iPatterns.Clean(); + pinBarZone.Clean(); + iPPatterns.Clean(); + XClean(resistances); + affectedZone.Clean(); + pullbackZone.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + XClean(doublePatterns); + pinBarZoneTrend.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/2.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/2.mq5 new file mode 100644 index 0000000..7770102 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/2.mq5 @@ -0,0 +1,843 @@ + +// +// Order Flow ... + +// +bool drawOrderFlow; +XBoxZone orderFlow[]; +bool manageOrderFlow; +ENUM_X_DIRECTION orderFlowDir; + +// +bool HasOrderFlow() +{ + // + return HasChild(orderFlow) && + HasDirection(orderFlowDir); +} + +// +bool HasBullishOrderFlow() +{ + return HasOrderFlow() && + IsXBullish(orderFlowDir); +} + +// +bool HasBearishOrderFlow() +{ + return HasOrderFlow() && + IsXBearish(orderFlowDir); +} + +// +bool GetOrderFlowBoundary( + double &upper, + double &lower // +) +{ + // + bool result = false; + + // + // Prepare ... + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + + // + // Validate ... + result = HasOrderFlow(); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Upper ... + idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + upper = orderFlow[idx].upper; + } + + // + // Lower ... + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + lower = orderFlow[idx].lower; + } + + // + result = NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + // Cleanup ... + if (!result) + { + // + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + } + + // + return result; +} + +// +bool ValidateOrderFlow(XOHCL &bar) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasOrderFlow(); + if (!result) + { + return result; + } + + // + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + result = GetOrderFlowBoundary(upper, lower); + result = result && + HasBullishOrderFlow() + ? bar.low > lower + : bar.high < upper; + + // + return result; +} + +// +void DrawOrderFlow() +{ + // + if (!drawOrderFlow || !HasOrderFlow()) + { + return; + } + + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); +} + +// +void ManageOrderFlow(XOHCL &bar) +{ + // + // Validate Exists ... + if (HasOrderFlow()) + { + // + if (!ValidateOrderFlow(bar)) + { + // + // Invalidate OrderFlow ... + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + } + + // + // Detect New ... + if (!HasOrderFlow()) + { + // + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // patternConfig.Default(); + // patternConfig.supportAndResistanceLoopbackLength = 21; + // patternConfig.supportAndResistanceValidationLength = 7; + + // + poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + } + + // + // Update Exists ... + if (HasOrderFlow()) + { + // + // Update to Times ... + UpdateToTime(orderFlow, TimeCurrent()); + + // + DrawOrderFlow(); + } +} + +// +// Zone ... + +// +XBoxZone support; +XBoxZone resistance; +bool drawZones; +bool drawSupport; +bool manageZones; +bool drawResistance; + +// +bool HasZones() +{ + return HasSupport() || + HasResistance(); +} + +// +bool HasSupport() +{ + return support.IsValid(); +} + +// +bool HasResistance() +{ + return resistance.IsValid(); +} + +// +bool ValidateZones(XOHCL &bar) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; +} + +// +void DrawZones() +{ + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } +} + +// +void ManageZones(XOHCL &bar) +{ + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + // + if (support.IsValid()) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + // + if (resistance.IsValid()) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASup"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); +} + +// +XBoxZone iSupport; +XBoxZone iResistance; +bool drawIZones; +bool drawISupport; +bool manageIZones; +bool drawIResistance; + +// +bool HasIZones() +{ + // + return HasISupport() || + HasIResistance(); +} + +// +bool HasISupport() +{ + return iSupport.IsValid(); +} + +// +bool HasIResistance() +{ + return iResistance.IsValid(); +} + +// +void DrawIZones() +{ + // + if (!drawIZones || !HasIZones()) + { + return; + } + + // + if (drawISupport && HasISupport()) + { + poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig); + } + + // + if (drawIResistance && HasIResistance()) + { + poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig); + } +} + +// +bool ValidateIZones(XOHCL &bar) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasIZones(); + if (!result) + { + return result; + } + + // + + // + // Support ... + bool hasSupport = HasISupport(); + if (hasSupport) + { + // + result = bar.close > iSupport.lower && + !IsBreaked(iSupport, X_PRICE_CLOSE); + if (!result) + { + // + iSupport.breakAt = bar.time; + iSupport.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasIResistance(); + if (hasResistance) + { + // + result = bar.close < iResistance.upper && + !IsBreaked(iResistance, X_PRICE_CLOSE); + if (!result) + { + // + iResistance.breakAt = bar.time; + iResistance.Clean(); + } + } + + // + result = + (hasSupport && !HasISupport()) || + (hasResistance && !HasIResistance()); + + // + return result; +} + +// +void ManageIZones(XOHCL &bar) +{ + // + // Validate Exists ... + if (HasIZones()) + { + // + if (!ValidateIZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(iSupport.breakAt)) + { + iSupport.Clean(); + } + + // + // Resistance ... + if (IsXValid(iResistance.breakAt)) + { + iResistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasIZones()) + { + // + if (HasISupport()) + { + // + iSupport.to = bar.time; + iSupport.type = "XFIMAISup"; + } + + // + if (HasIResistance()) + { + // + iResistance.to = bar.time; + iResistance.type = "XFIMAIRes"; + } + + // + DrawIZones(); + } +} + +// +// Trends ... + +// +XTrend scTrend; +XTrend mcTrend; +XTrend lcTrend; +XTrend hcTrend; + +// +bool drawTrends; +bool drawSCTrend; +bool drawMCTrend; +bool drawLCTrend; +bool drawHCTrend; +bool manageTrends; + +// +bool HasTrend() +{ + // + bool result = + HasSCTrend() || + HasMCTrend() || + HasLCTrend() || + HasHCTrend(); + + // + return result; +} + +// +bool HasSCTrend() +{ + return scTrend.IsValid() && + scTrend.HasTrend(); +} + +// +bool HasMCTrend() +{ + return mcTrend.IsValid() && + mcTrend.HasTrend(); +} + +// +bool HasLCTrend() +{ + return lcTrend.IsValid() && + lcTrend.HasTrend(); +} + +// +bool HasHCTrend() +{ + return hcTrend.IsValid() && + hcTrend.HasTrend(); +} + +// +void DrawTrends() +{ + // + if (!drawTrends || !HasTrend()) + { + return; + } + + // + // SC ... + if (drawSCTrend && HasSCTrend()) + { + poiDrawer.DrawTrendLine(scTrend, structureDrawConfig.drawConfig); + } + + // + // MC ... + if (drawMCTrend && HasMCTrend()) + { + poiDrawer.DrawTrendLine(mcTrend, structureDrawConfig.drawConfig); + } + + // + // LC ... + if (drawLCTrend && HasLCTrend()) + { + poiDrawer.DrawTrendLine(lcTrend, structureDrawConfig.drawConfig); + } + + // + // HC ... + if (drawHCTrend && HasHCTrend()) + { + poiDrawer.DrawTrendLine(hcTrend, structureDrawConfig.drawConfig); + } +} + +// +void ManageTrends(XOHCL &bar) +{ + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XTrend tmpTrend; + + // + // SC ... + tmpTrend.Clean(); + has = fimaParser.HasSCTrend(tmpTrend, bar.Index()); + if (has) + { + scTrend = tmpTrend; + } + + // + // MC ... + tmpTrend.Clean(); + has = fimaParser.HasMCTrend(tmpTrend, bar.Index()); + if (has) + { + mcTrend = tmpTrend; + } + + // + // LC ... + tmpTrend.Clean(); + has = fimaParser.HasLCTrend(tmpTrend, bar.Index()); + if (has) + { + lcTrend = tmpTrend; + } + + // + // HC ... + tmpTrend.Clean(); + has = fimaParser.HasHCTrend(tmpTrend, bar.Index()); + if (has) + { + hcTrend = tmpTrend; + } + + // + DrawTrends(); + + // + // Cleanup ... + tmpTrend.Clean(); +} + +// +void Manage(XOHCL &bar) +{ + // + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + has = bar.GetPreviousBar(pBar); + has = has && + pBar.GetPreviousBar(p2Bar); + has = has && + p2Bar.GetPreviousBar(p3Bar); + if (!has) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + ManageTrends(bar); + ManageZones(p2Bar); + ManageIZones(p2Bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); +} + +// +// Configure ... +drawZones = false; +drawIZones = false; +drawTrends = false; +drawSCTrend = false; +drawMCTrend = false; +drawLCTrend = false; +drawHCTrend = false; +drawSupport = false; +drawISupport = false; +drawOrderFlow = false; +drawResistance = false; +drawIResistance = false; + +// +manageZones = true; +manageIZones = true; +manageTrends = false; +manageOrderFlow = true; + +// +// Manage ... +Manage(iBar); diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/3.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/3.mq5 new file mode 100644 index 0000000..25ddcd1 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/3.mq5 @@ -0,0 +1,496 @@ + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validator Flags ... + bool validateByZones = true; + bool validateByPinBar = true; + bool validateByBarPatterns = true; + bool validateByCyclesTrend = true; + bool validateByMaFastSlowGrows = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysis p3BarPatterns; + XPatternAnalysisConfig iPatternsConfig; + + // + // Reading Bars ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading Bar Patterns ... + iPatternsConfig.Default(); + iPatternsConfig.FullPattern(); + result = + result && + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p3Bar, + p3BarPatterns, + iPatternsConfig // + ); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } + + // + // Detect a Cross of MAs ... + bool isFastCrossedOverSlow = fimaParser.IsMAFastCrossedOverSlow(p2Bar.Index()); + bool isFastCrossedUnderSlow = fimaParser.IsMAFastCrossedUnderSlow(p2Bar.Index()); + + // + isBullish = isFastCrossedOverSlow; + isBearish = isFastCrossedUnderSlow; + + // + result = isBullish || isBearish; + + // + // Validate Cross By Over/Under Last ... + if (result && validateByMaFastSlowGrows) + { + // + // Bullish ... + bool isFastOverLast = fimaParser.IsMAFastOverLast(pBar.Index()); + bool isSlowOverLast = fimaParser.IsMASlowOverLast(pBar.Index()); + bool isOverLast = isFastOverLast && isSlowOverLast; + + // + // Bearish ... + bool isFastUnderLast = fimaParser.IsMAFastUnderLast(pBar.Index()); + bool isSlowUnderLast = fimaParser.IsMASlowUnderLast(pBar.Index()); + bool isUnderLast = isFastUnderLast && isSlowUnderLast; + + // + isBullish = + isBullish && + isOverLast; + + // + isBearish = + isBearish && + isUnderLast; + + // + result = isBullish || isBearish; + } + + // + // Validate By Cycles Trend ... + if (result && validateByCyclesTrend) + { + // + // Reading Cycles Trend ... + + // + // Bullish ... + + // + bool isLCMABullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCMABullish = fimaParser.IsHCMABullish(pBar.Index()); + + // + bool isLCMAOverLast = fimaParser.IsLCMAOverLast(pBar.Index()); + bool isHCMAOverLast = fimaParser.IsHCMAOverLast(pBar.Index()); + + // + bool isCyclesMABullish = isLCMABullish && isHCMABullish && isLCMAOverLast && isHCMAOverLast; + + // + // Bearish ... + + // + bool isLCMABearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCMABearish = fimaParser.IsHCMABearish(pBar.Index()); + + // + bool isLCMAUnderLast = fimaParser.IsLCMAUnderLast(pBar.Index()); + bool isHCMAUnderLast = fimaParser.IsHCMAUnderLast(pBar.Index()); + + // + bool isCyclesMABearish = isLCMABearish && isHCMABearish && isLCMAUnderLast && isHCMAUnderLast; + + // + isBullish = + isBullish && + isCyclesMABullish; + + // + isBearish = + isBearish && + isCyclesMABearish; + + // + result = isBullish || isBearish; + } + + // + // Validate Has a PinBar ... + if (result && validateByPinBar) + { + // + bool isPBarIsPinBar = poiDetector.IsPinnedBar(pBar, dir); + bool isPBarIsPinBarBullish = isPBarIsPinBar && IsXBullish(dir); + bool isPBarIsPinBarBearish = isPBarIsPinBar && IsXBearish(dir); + + // + bool isP2BarIsPinBar = poiDetector.IsPinnedBar(p2Bar, dir); + bool isP2BarIsPinBarBullish = isP2BarIsPinBar && IsXBullish(dir); + bool isP2BarIsPinBarBearish = isP2BarIsPinBar && IsXBearish(dir); + + // + bool isBullishPin = isPBarIsPinBarBullish || isP2BarIsPinBarBullish; + bool isBearishPin = isPBarIsPinBarBearish || isP2BarIsPinBarBearish; + + // + isBullish = + isBullish && + isBullishPin; + + // + isBearish = + isBearish && + isBearishPin; + + // + result = isBullish || isBearish; + } + + // + // Validate By Bar Patterns ... + if (result && validateByBarPatterns) + { + // + int count = 0; + int bullishCount = 0; + int bearishCount = 0; + + // + count = pBarPatterns.Count(X_DIRECTION_BULLISH); + bullishCount += count; + + // + count = p2BarPatterns.Count(X_DIRECTION_BULLISH); + bullishCount += count; + + // + count = pBarPatterns.Count(X_DIRECTION_BEARISH); + bearishCount += count; + + // + count = p2BarPatterns.Count(X_DIRECTION_BEARISH); + bearishCount += count; + + // + bool hasBullishScore = IsValidSize(bullishCount) && + bullishCount > bearishCount; + + // + bool hasBearishScore = IsValidSize(bearishCount) && + bearishCount > bullishCount; + + // + // Reading Bar Patterns ... + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (pBarPatterns.HasPattern(X_BAR_PATTERN_FLAG, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_STAR, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_RISING, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_MOMENTUM, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_PIERCING, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BULLISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_TRUE_GAPED, X_DIRECTION_BULLISH)); + bool isP2BarHasBullishPatterns = + (p2BarPatterns.HasPattern(X_BAR_PATTERN_FLAG, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_STAR, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_RISING, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_MOMENTUM, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_PIERCING, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BULLISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_TRUE_GAPED, X_DIRECTION_BULLISH)); + bool hasBullishPatterns = isPBarHasBullishPatterns || isP2BarHasBullishPatterns; + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (pBarPatterns.HasPattern(X_BAR_PATTERN_FLAG, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_STAR, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_RISING, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_MOMENTUM, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_PIERCING, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BEARISH) || + pBarPatterns.HasPattern(X_BAR_PATTERN_TRUE_GAPED, X_DIRECTION_BEARISH)); + bool isP2BarHasBearishPatterns = + (p2BarPatterns.HasPattern(X_BAR_PATTERN_FLAG, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_STAR, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_RISING, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_MOMENTUM, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_PIERCING, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BEARISH) || + p2BarPatterns.HasPattern(X_BAR_PATTERN_TRUE_GAPED, X_DIRECTION_BEARISH)); + bool hasBearishPatterns = isPBarHasBearishPatterns || isP2BarHasBearishPatterns; + + // + isBullish = + isBullish && + hasBullishScore && + hasBullishPatterns; + + // + isBearish = + isBearish && + hasBearishScore && + hasBearishPatterns; + + // + result = isBullish || isBearish; + } + + // + // Validate By Zones ... + if (result && validateByZones) + { + // + XBoxZone zones[]; + int count = poiDetector.DetectZones( + pBar, + zones, + true, // Validate Zones ... + false, // OB ... + true, // FVG ... + true, // Supports ... + true, // Resistances ... + X_DIRECTION_NONE, // All Directions ... + X_SORT_BY_DATE, // Sort By ... + X_DIRECTION_BEARISH, // Sort Direction ... + 5, // Zones Loopback ... + 5, // Zones Validation ... + 100 // Loopback ... + ); + + // + bool has = IsValidSize(count); + if (has) + { + poiDrawer.DrawZones(zones, structureDrawConfig.drawConfig); + } + } + + // + if (result) + { + // + DebugBreak(); + + // + result = false; + isBullish = false; + isBearish = false; + } + + // + // Detecting Direction ... + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + // Since Zone Prepared in Above Steps ... + // here we only Validate it ... + result = zone.IsValid(); + } + + // + // Draws ... + if (result) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + XPatternAnalysisDrawConfig iPatternsConfig = structureDrawConfig.barAnalysisDrawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + // Draw Zone ... + if (zone.IsValid()) + { + // + iConfig.zonesStyle = STYLE_DASHDOT; + iConfig.bullishColor = clrYellow; + iConfig.bearishColor = clrDarkOrange; + + // + poiDrawer.DrawZone(zone, iConfig); + } + + // + // poiDrawer.DrawZone(mcPVZone, iConfig); + // poiDrawer.DrawZone(lcPVZone, iConfig); + // poiDrawer.DrawZone(hcPVZone, iConfig); + + // + // poiDrawer.DrawZone(pinBarZone, iConfig); + // poiDrawer.DrawZone(pullbackZone, iConfig); + // poiDrawer.DrawTrendLine(pinBarZoneTrend, iConfig); + + // + poiDrawer.DrawPatternAnalysis(pBarPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(p2BarPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(p3BarPatterns, iPatternsConfig); + + // + // if (hasATRBox) + // { + // poiDrawer.DrawZone(atrBox, iConfig); + // } + + // + // if (hasDoublePatterns) + // { + // // + // poiDrawer.DrawPatternAnalysis(iPatterns, iPatternsConfig); + // poiDrawer.DrawPatternAnalysis(iPPatterns, iPatternsConfig); + // } + + // + iConfig.Clean(); + iPatternsConfig.Clean(); + + // + DebugBreak(); + + // // + // result = false; + // isBullish = false; + // isBearish = false; + // zone.Clean(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/Test.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/Test.mq5 new file mode 100644 index 0000000..e3433d9 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/Test.mq5 @@ -0,0 +1,949 @@ + +/** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateByBarPatterns = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + bool isConsolidation = poiDetector.DetectXPVZone(zone, p2Bar.Index()); + + // + isBullish = + isConsolidation && + zone.IsBullish(); + + // + isBearish = + isConsolidation && + zone.IsBearish(); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + if (result) + { + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + DebugBreak(); + + // + result = false; + isBullish = false; + isBearish = false; + } + + // // + // // Validate based on Bars Patterns ... + // bool validateByBarPatterns = true; + // if (validateByBarPatterns) + // { + // // + // // Reading pBar Patterns ... + // XPatternAnalysis pBarAnalysis; + // poiDetector.AnalyseBarPatterns( + // pBar, + // pBarAnalysis, + // structureConfig.barsAnalysisConfig // + // ); + + // // + // // Bullish ... + // bool isPBarHasBullishPatterns = + // (bar.close > pBar.low || + // bar.open > pBar.low) && + // ( + // // + // pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // // + // ); + + // // + // // Bearish ... + // bool isPBarHasBearishPatterns = + // (bar.close < pBar.high || + // bar.open < pBar.high) && + // ( + // // + // pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // // + // ); + + // // + // isBullish = + // isBullish && + // isPBarHasBullishPatterns && + // !isPBarHasBearishPatterns; + + // // + // isBearish = + // isBearish && + // isPBarHasBearishPatterns && + // !isPBarHasBullishPatterns; + + // // + // // Summarize Result ... + // result = isBullish || + // isBearish; + // } + + // // + // // Checking PullBack ... + // bool validateByPullback = false; + // if (validateByPullback) + // { + // // + // XBoxZone pullback; + // ENUM_X_DIRECTION pullbackDir; + // bool isPullBack = result && + // poiDetector.IsPullbackPattern( + // pBar, + // pullback, + // pullbackDir, + // 2, + // false // Force Break ... + // ); + // bool isPullbackBullish = isPullBack && + // IsXBullish(pullbackDir); + // bool isPullbackBearish = isPullBack && + // IsXBearish(pullbackDir); + + // // + // isBullish = + // isBullish && + // isPullbackBullish; + + // // + // isBearish = + // isBearish && + // isPullbackBearish; + + // // + // // Summarize Result ... + // result = isBullish || + // isBearish; + // } + + // + // Validate ... + result = isBullish || + isBearish; + + // + // Prepare Zone ... + if (result) + { + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + + // + return result; +} + +// // +// bool isConsolidation = poiDetector.DetectXPVZone(zone, p2Bar.Index()); + +// // +// isBullish = +// isConsolidation && +// zone.IsBullish(); + +// // +// isBearish = +// isConsolidation && +// zone.IsBearish(); + +// // +// // Summarize Result ... +// result = isBullish || isBearish; + +// // +// // Force PBar Has Pattern ... +// if (result && validateByBarPatterns) +// { +// // +// // Analyse Bar Patterns ... +// result = pBarPatterns.IsValid(); + +// // +// // Bullish ... +// bool isPBarHasBullishPatterns = +// result && +// ( +// // +// pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || +// pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || +// pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || +// pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || +// pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) +// // +// ); + +// // +// // Bearish ... +// bool isPBarHasBearishPatterns = +// result && +// ( +// // +// pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || +// pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || +// pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || +// pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || +// pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) +// // +// ); + +// // +// isBullish = +// isBullish && +// isPBarHasBullishPatterns && +// !isPBarHasBearishPatterns; + +// // +// isBearish = +// isBearish && +// isPBarHasBearishPatterns && +// !isPBarHasBullishPatterns; + +// // +// // Summarize Result ... +// result = isBullish || isBearish; + +// // +// // Reset Flags ... +// if (!result) +// { +// // +// isBullish = false; +// isBearish = false; +// } +// } + +// // +// if (result) +// { +// // +// poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); +// poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); +// DebugBreak(); + +// // +// result = false; +// isBullish = false; +// isBearish = false; +// } + +// // +// // Validate based on Bars Patterns ... +// bool validateByBarPatterns = true; +// if (validateByBarPatterns) +// { +// // +// // Reading pBar Patterns ... +// XPatternAnalysis pBarAnalysis; +// poiDetector.AnalyseBarPatterns( +// pBar, +// pBarAnalysis, +// structureConfig.barsAnalysisConfig // +// ); + +// // +// // Bullish ... +// bool isPBarHasBullishPatterns = +// (bar.close > pBar.low || +// bar.open > pBar.low) && +// ( +// // +// pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) +// // +// ); + +// // +// // Bearish ... +// bool isPBarHasBearishPatterns = +// (bar.close < pBar.high || +// bar.open < pBar.high) && +// ( +// // +// pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) +// // +// ); + +// // +// isBullish = +// isBullish && +// isPBarHasBullishPatterns && +// !isPBarHasBearishPatterns; + +// // +// isBearish = +// isBearish && +// isPBarHasBearishPatterns && +// !isPBarHasBullishPatterns; + +// // +// // Summarize Result ... +// result = isBullish || +// isBearish; +// } + +// // +// // Checking PullBack ... +// bool validateByPullback = false; +// if (validateByPullback) +// { +// // +// XBoxZone pullback; +// ENUM_X_DIRECTION pullbackDir; +// bool isPullBack = result && +// poiDetector.IsPullbackPattern( +// pBar, +// pullback, +// pullbackDir, +// 2, +// false // Force Break ... +// ); +// bool isPullbackBullish = isPullBack && +// IsXBullish(pullbackDir); +// bool isPullbackBearish = isPullBack && +// IsXBearish(pullbackDir); + +// // +// isBullish = +// isBullish && +// isPullbackBullish; + +// // +// isBearish = +// isBearish && +// isPullbackBearish; + +// // +// // Summarize Result ... +// result = isBullish || +// isBearish; +// } + +/** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateByBarPatterns = false; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + bool hasSupport = p2BarPatterns.IsValid() && + p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsValid() && + p2BarPatterns.IsResistance(); + + // + isBullish = + hasSupport && + p2BarPatterns.Count(X_DIRECTION_BULLISH) >= 4; + + // + isBearish = + hasResistance && + p2BarPatterns.Count(X_DIRECTION_BEARISH) >= 4; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Extract Affected Zone ... + if (result) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone tmpZone; + + // + if (hasSupport) + { + // + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + isBullish = + isBullish && + hasSupport && + (IsActed(pBar, tmpZone) || + IsTested(pBar, tmpZone)); + } + + // + if (hasResistance) + { + // + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + isBearish = + isBearish && + hasResistance && + (IsActed(pBar, tmpZone) || + IsTested(pBar, tmpZone)); + } + + // + // Cleanup ... + tmpBar.Clean(); + tmpZone.Clean(); + tmpPivot.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate based on Bars Patterns ... + if (result && validateByBarPatterns) + { + // + // Bullish... + bool isPBarHasBullishPatterns = + pBarPatterns.IsValid() && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + pBarPatterns.IsValid() && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + if (result) + { + // + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + poiDrawer.DrawPatternAnalysis(p2BarPatterns, structureDrawConfig.barAnalysisDrawConfig); + DebugBreak(); + + // + result = false; + isBullish = false; + isBearish = false; + } + + // // + // bool isConsolidation = poiDetector.DetectXPVZone(zone, p2Bar.Index()); + + // // + // isBullish = + // isConsolidation && + // zone.IsBullish(); + + // // + // isBearish = + // isConsolidation && + // zone.IsBearish(); + + // // + // // Summarize Result ... + // result = isBullish || isBearish; + + // // + // // Force PBar Has Pattern ... + // if (result && validateByBarPatterns) + // { + // // + // // Analyse Bar Patterns ... + // result = pBarPatterns.IsValid(); + + // // + // // Bullish ... + // bool isPBarHasBullishPatterns = + // result && + // ( + // // + // pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + // pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + // pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + // pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + // pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // // + // ); + + // // + // // Bearish ... + // bool isPBarHasBearishPatterns = + // result && + // ( + // // + // pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + // pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + // pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + // pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + // pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // // + // ); + + // // + // isBullish = + // isBullish && + // isPBarHasBullishPatterns && + // !isPBarHasBearishPatterns; + + // // + // isBearish = + // isBearish && + // isPBarHasBearishPatterns && + // !isPBarHasBullishPatterns; + + // // + // // Summarize Result ... + // result = isBullish || isBearish; + + // // + // // Reset Flags ... + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + // } + + // // + // if (result) + // { + // // + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + // DebugBreak(); + + // // + // result = false; + // isBullish = false; + // isBearish = false; + // } + + // // + // // Checking PullBack ... + // bool validateByPullback = false; + // if (validateByPullback) + // { + // // + // XBoxZone pullback; + // ENUM_X_DIRECTION pullbackDir; + // bool isPullBack = result && + // poiDetector.IsPullbackPattern( + // pBar, + // pullback, + // pullbackDir, + // 2, + // false // Force Break ... + // ); + // bool isPullbackBullish = isPullBack && + // IsXBullish(pullbackDir); + // bool isPullbackBearish = isPullBack && + // IsXBearish(pullbackDir); + + // // + // isBullish = + // isBullish && + // isPullbackBullish; + + // // + // isBearish = + // isBearish && + // isPullbackBearish; + + // // + // // Summarize Result ... + // result = isBullish || + // isBearish; + // } + + // + // Validate ... + result = isBullish || + isBearish; + + // + // Prepare Zone ... + if (result) + { + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + patternConfig.Clean(); + p2BarPatterns.Clean(); + + // + return result; +} + +bool validateByPVChange = false; +bool validateByPVInside = false; + +// +// Validate By PV Inside ... +if (result && validateByPVInside) +{ + // + double pVale = fimaHelper.GetVale(pBar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + + // + bool isValePassed = pVale <= support.upper && + pVale >= support.upper && + fimaParser.IsValeSame(pBar.Index()); + + // + bool isPeakPassed = pPeak <= resistance.upper && + pPeak >= resistance.upper && + fimaParser.IsPeakSame(pBar.Index()); + + // + isBullish = + isBullish && + isValePassed; + + // + isBearish = + isBearish && + isPeakPassed; + + // + // Summarize Result ... + result = isBullish || isBearish; +} + +// +// Validate by PV Change ... +if (result && validateByPVChange) +{ + // + // bullish => p3, p2 vale under last ... + // bearish => p3, p2 peak over last ... + + // + bool isValePassed = + fimaParser.IsValeUnderLast(p2Bar.Index()) || + fimaParser.IsValeUnderLast(p3Bar.Index()); + + // + bool isPeakPassed = + fimaParser.IsPeakOverLast(p2Bar.Index()) || + fimaParser.IsPeakOverLast(p3Bar.Index()); + + // + isBullish = + isBullish && + isValePassed; + + // + isBearish = + isBearish && + isPeakPassed; + + // + // Summarize Result ... + result = isBullish || isBearish; +} diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/signallers.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/signallers.mq5 new file mode 100644 index 0000000..c2e811c --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/signallers.mq5 @@ -0,0 +1,1029 @@ + +// ======================================= +// Temp Signaller: +// ======================================= + +/** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool StrategyXHasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Do ... + + // + isBullish = + // + false + // + ; + + // + isBearish = + // + false + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Manage Stops ... + if (result) + { + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; +} + +// ======================================= +// Signallers: +// ======================================= + +/** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Reading Conditions ... + int pullBackStartBar = -1; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + zone, + dir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(dir); + bool isPullbackBearish = isPullBack && + IsXBearish(dir); + if (isPullBack) + { + pullBackStartBar = zone.FromIndex(); + } + + // + // Reading HK Bond ... + + // + double pHKBondUpper = fimaHelper.GetHKBondUpper(pBar.Index()); + double pHKBondLower = fimaHelper.GetHKBondLower(pBar.Index()); + int overHKBondUpperCount = fimaHelper.CountOverHKBondUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBondLowerCount = fimaHelper.CountUnderHKBondLower(pullBackStartBar, X_PRICE_HIGH); + + // + // Reading PV Requirements ... + + // + int lastPeakOverLastIDX = -1; + int lastValeUnderLastIDX = -1; + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + int samePeaks = fimaHelper.CountSamePeaks(pBar.Index()); + int sameVales = fimaHelper.CountSameVales(pBar.Index()); + fimaHelper.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaHelper.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + + // + // Try To Find Affected Zone ... + + // + // Collecting Zones ... + XBoxZone zones[]; + XBoxZone affectedZones[]; + XBoxZone affectedZonesBullish[]; + XBoxZone affectedZonesBearish[]; + int zonesCount = poiDetector.CollectZones( + pBar, + zones, // + 5, // Zones Loopback ... + 3 // Zones Validation Length ... + // Required Zones ... + // Loopback ... + ); + int affectedZonesCount = ExtractAffectedZones( + pBar, + zones, + affectedZones // + ); + int affectedZonesBullishCount = ExtractByDirection( + affectedZonesBullish, + affectedZones, + X_DIRECTION_BULLISH // + ); + int affectedZonesBearishCount = ExtractByDirection( + affectedZonesBearish, + affectedZones, + X_DIRECTION_BEARISH // + ); + + // + int insideBullishIDX = -1; + int insideBearishIDX = -1; + bool hasBullishInside = + pBar.IsBullish() && + HasInside( + insideBullishIDX, + pBar, + affectedZonesBullish // + ); + bool hasBearishInside = + pBar.IsBearish() && + HasInside( + insideBearishIDX, + pBar, + affectedZonesBearish // + ); + + // + // Do ... + + // + isBullish = + // + hasBullishInside && + isPullbackBullish && + isPBarHasBullishPatterns && + fimaHelper.IsSarBullish(pBar.Index()) && + (pVale >= affectedZonesBullish[insideBullishIDX].lower && + pVale <= affectedZonesBullish[insideBullishIDX].upper) + // + ; + + // + isBearish = + // + hasBearishInside && + isPullbackBearish && + isPBarHasBearishPatterns && + fimaHelper.IsSarBearish(pBar.Index()) && + (pPeak >= affectedZonesBearish[insideBearishIDX].lower && + pPeak <= affectedZonesBearish[insideBearishIDX].upper) + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + if (isBullish) + { + // + poiDrawer.DrawZone( + affectedZonesBullish[insideBullishIDX], + structureDrawConfig.drawConfig // + ); + } + else + { + // + poiDrawer.DrawZone( + affectedZonesBearish[insideBearishIDX], + structureDrawConfig.drawConfig // + ); + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + if (isBullish) + { + zone = affectedZonesBullish[insideBullishIDX]; + } + else + { + zone = affectedZonesBearish[insideBearishIDX]; + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + XClean(zones); + pBarAnalysis.Clean(); + XClean(affectedZones); + XClean(affectedZonesBullish); + XClean(affectedZonesBearish); + + // + return result; +} + +/** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaHelper.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaHelper.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaHelper.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaHelper.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Do ... + + // + isBullish = + // + isFastOverLast && + isValeUnderLast && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + isPeakOverLast && + isFastUnderLast && + !isP2ValeOverLast && + isPBarCloseUnderFast && + isP2BarBearishPinned && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Manage Stops ... + if (result) + { + // + double entry = GetEntry(zone.symbol, zone.dir); + double riskSide = zone.IsBullish() ? zone.lower : zone.upper; + double risk = MathAbs(entry - riskSide); + + // + // Collecting Affected Zones ... + XBoxZone tmps[]; + XBoxZone zones[]; + XBoxZone actedZones[]; + XBoxZone insideZones[]; + XBoxZone breakedZones[]; + XBoxZone affectedZones[]; + + // + // Support and Resistances ... + poiDetector.CollectZones(bar, tmps); + Copy(tmps, zones, false); + + // + // OBS ... + poiDetector.CollectOBs(bar, tmps); + Copy(tmps, zones, false); + + // + // FVGs ... + poiDetector.CollectFVGs(bar, tmps); + Copy(tmps, zones, false); + + // + ExtractAffectedZones(bar, zones, affectedZones); + + // + // Acteds Zones ... + ExtractActeds(bar, actedZones, affectedZones); + + // + // Inside Zones ... + ExtractInsides(bar, insideZones, affectedZones); + + // + // Breaked Zones ... + ExtractBreakeds(bar, breakedZones, affectedZones); + + // + // Draw Affected Zones ... + if (HasChild(affectedZones)) + { + // + UpdateToTime(affectedZones, bar.time); + poiDrawer.DrawZones(affectedZones, structureDrawConfig.drawConfig); + } + + // + // Draw Acted Zones ... + // if (HasChild(actedZones)) + // { + // poiDrawer.DrawZones(actedZones, structureDrawConfig.drawConfig); + // } + + // + // Draw Inside Zones ... + // if (HasChild(insideZones)) + // { + // poiDrawer.DrawZones(insideZones, structureDrawConfig.drawConfig); + // } + + // // + // // Draw Breaked Zones ... + // if (HasChild(breakedZones)) + // { + // poiDrawer.DrawZones(breakedZones, structureDrawConfig.drawConfig); + // } + + // + // Cleanup ... + XClean(tmps); + XClean(zones); + XClean(actedZones); + XClean(insideZones); + XClean(breakedZones); + XClean(affectedZones); + } + + // + if (result) + { + // + zone.to = bar.time; + + // + poiDrawer.DrawZone( + zone, + structureDrawConfig.drawConfig // + ); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; +} + +/** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Do ... + // XFIMA Consolidation ... + + // + bool isConsolidation = fimaHelper.HasPVConsolidationZone( + zone, + pBar.Index(), + true, // Force PV Break ... + true // Force Has Sar Switch ... + ); + + // + isBullish = + isConsolidation && + zone.IsBullish(); + + // + isBearish = + isConsolidation && + zone.IsBearish(); + + // + // Validate based on Bars Patterns ... + bool validateByBarPatterns = true; + if (validateByBarPatterns) + { + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || + isBearish; + } + + // + // Checking PullBack ... + bool validateByPullback = false; + if (validateByPullback) + { + // + XBoxZone pullback; + ENUM_X_DIRECTION pullbackDir; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + pullback, + pullbackDir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(pullbackDir); + bool isPullbackBearish = isPullBack && + IsXBearish(pullbackDir); + + // + isBullish = + isBullish && + isPullbackBullish; + + // + isBearish = + isBearish && + isPullbackBearish; + + // + // Summarize Result ... + result = isBullish || + isBearish; + } + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = zone.dir; + zone.to = bar.time; + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.zonesWidth = 3; + iConfig.bullishColor = clrYellow; + iConfig.bearishColor = clrDarkOrange; + poiDrawer.DrawZone(zone, iConfig); + Print("Consolidation"); + } + + // + // Prepare Zone ... + if (result) + { + // + // zone.Clean(); + // result = ToBox( + // p2Bar, + // zone, + // dir, + // X_BAR_PATTERN_PINNED // + // ); + + // + // Manage Stops ... + if (result) + { + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; +} diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 2.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 2.mq5 new file mode 100644 index 0000000..40fdf46 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 2.mq5 @@ -0,0 +1,3727 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure ... + drawLeg = false; + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + manageLegs = true; + manageZones = true; + manageIZones = true; + manageTrends = false; + manageOrderFlow = true; + + // + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Manage ... + Manage(iBar); + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + + // + // Remove TP if in Profit SL ... + iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + has = + (positions[i].IsBullish() && HasResistance()) + ? (iGuard.sl >= iValue && + positions[i].tp < resistance.lower) + : (positions[i].IsBearish() && HasSupport()) + ? (iGuard.sl <= iValue && + positions[i].tp > support.upper) + : false; + if (has) + { + // + iGuard.Clean(); + iGuard.force = false; + iGuard.tp = positions[i].IsBullish() + ? resistance.lower + : support.upper; + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + } + } + } + } + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + void Manage(XOHCL &bar) + { + // + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + has = bar.GetPreviousBar(pBar); + has = has && + pBar.GetPreviousBar(p2Bar); + has = has && + p2Bar.GetPreviousBar(p3Bar); + if (!has) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + ManageLeg(bar); + ManageTrends(bar); + ManageZones(p2Bar); + ManageIZones(p2Bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + // Private ... + private: + // + // Props ... + + // + // Leg ... + + XLeg leg; // Exists Leg ... + bool drawLeg; // Draw Leg ... + bool manageLegs; + + // + bool HasLeg() + { + return leg.IsValid(); + } + + // + bool ValidateLeg(XOHCL &bar) + { + // + bool result = false; + + // + result = HasLeg() && + bar.IsValid(); + if (!result) + { + return result; + } + + // + result = + leg.IsBullish() + ? bar.low > leg.lower + : leg.IsBearish() + ? bar.high < leg.upper + : false; + + // + return result; + } + + // + void DrawLeg() + { + // + if (!drawLeg) + { + return; + } + + // + if (!HasLeg()) + { + return; + } + + // + // Update to Times ... + leg.UpdateTimes(); + + // + // Draw Leg Box ... + XBoxZone legZone; + leg.ToBox(legZone); + if (legZone.IsValid()) + { + // + legZone.to = TimeCurrent(); + poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig); + } + + // + // Draw Legs Other Stufs ... + return; + + // + // FVGs ... + poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig); + + // + // Support and Resistances ... + poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig); + + // + // Patterns ... + poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig); + } + + // + void ManageLeg(XOHCL &bar) + { + // + // Validate Exists ... + if (HasLeg()) + { + // + if (!ValidateLeg(bar)) + { + // + // Invalidate XLeg ... + leg.Clean(); + } + } + + // + // Detect New ... + if (!HasLeg()) + { + poiDetector.IsLegPattern(bar, leg); + } + + // + // Update Exists ... + if (HasLeg()) + { + // + // Update to Times ... + leg.UpdateTimes(); + + // + DrawLeg(); + } + } + + // + // Order Flow ... + + // + bool drawOrderFlow; + XBoxZone orderFlow[]; + bool manageOrderFlow; + ENUM_X_DIRECTION orderFlowDir; + + // + bool HasOrderFlow() + { + // + return HasChild(orderFlow) && + HasDirection(orderFlowDir); + } + + // + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + // + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + + // + bool GetOrderFlowBoundary( + double &upper, + double &lower // + ) + { + // + bool result = false; + + // + // Prepare ... + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + + // + // Validate ... + result = HasOrderFlow(); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Upper ... + idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + upper = orderFlow[idx].upper; + } + + // + // Lower ... + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + lower = orderFlow[idx].lower; + } + + // + result = NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + // Cleanup ... + if (!result) + { + // + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + } + + // + return result; + } + + // + bool ValidateOrderFlow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasOrderFlow(); + if (!result) + { + return result; + } + + // + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + result = GetOrderFlowBoundary(upper, lower); + result = result && + HasBullishOrderFlow() + ? bar.low > lower + : bar.high < upper; + + // + return result; + } + + // + void DrawOrderFlow() + { + // + if (!drawOrderFlow || !HasOrderFlow()) + { + return; + } + + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); + } + + // + void ManageOrderFlow(XOHCL &bar) + { + // + // Validate Exists ... + if (HasOrderFlow()) + { + // + if (!ValidateOrderFlow(bar)) + { + // + // Invalidate OrderFlow ... + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + } + + // + // Detect New ... + if (!HasOrderFlow()) + { + // + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // patternConfig.Default(); + // patternConfig.supportAndResistanceLoopbackLength = 21; + // patternConfig.supportAndResistanceValidationLength = 7; + + // + poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + } + + // + // Update Exists ... + if (HasOrderFlow()) + { + // + // Update to Times ... + UpdateToTime(orderFlow, TimeCurrent()); + + // + DrawOrderFlow(); + } + } + + // + // Zone ... + + // + XBoxZone support; + XBoxZone resistance; + bool drawZones; + bool drawSupport; + bool manageZones; + bool drawResistance; + + // + bool HasZones() + { + return HasSupport() || + HasResistance(); + } + + // + bool HasSupport() + { + return support.IsValid(); + } + + // + bool HasResistance() + { + return resistance.IsValid(); + } + + // + bool ValidateZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; + } + + // + void DrawZones() + { + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } + } + + // + void ManageZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + // + if (support.IsValid()) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + // + if (resistance.IsValid()) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASup"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + XBoxZone iSupport; + XBoxZone iResistance; + bool drawIZones; + bool drawISupport; + bool manageIZones; + bool drawIResistance; + + // + bool HasIZones() + { + // + return HasISupport() || + HasIResistance(); + } + + // + bool HasISupport() + { + return iSupport.IsValid(); + } + + // + bool HasIResistance() + { + return iResistance.IsValid(); + } + + // + void DrawIZones() + { + // + if (!drawIZones || !HasIZones()) + { + return; + } + + // + if (drawISupport && HasISupport()) + { + poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig); + } + + // + if (drawIResistance && HasIResistance()) + { + poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig); + } + } + + // + bool ValidateIZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasIZones(); + if (!result) + { + return result; + } + + // + + // + // Support ... + bool hasSupport = HasISupport(); + if (hasSupport) + { + // + result = bar.close > iSupport.lower && + !IsBreaked(iSupport, X_PRICE_CLOSE); + if (!result) + { + // + iSupport.breakAt = bar.time; + iSupport.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasIResistance(); + if (hasResistance) + { + // + result = bar.close < iResistance.upper && + !IsBreaked(iResistance, X_PRICE_CLOSE); + if (!result) + { + // + iResistance.breakAt = bar.time; + iResistance.Clean(); + } + } + + // + result = + (hasSupport && !HasISupport()) || + (hasResistance && !HasIResistance()); + + // + return result; + } + + // + void ManageIZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasIZones()) + { + // + if (!ValidateIZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(iSupport.breakAt)) + { + iSupport.Clean(); + } + + // + // Resistance ... + if (IsXValid(iResistance.breakAt)) + { + iResistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasIZones()) + { + // + if (HasISupport()) + { + // + iSupport.to = bar.time; + iSupport.type = "XFIMAISup"; + } + + // + if (HasIResistance()) + { + // + iResistance.to = bar.time; + iResistance.type = "XFIMAIRes"; + } + + // + DrawIZones(); + } + } + + // + // Trends ... + + // + XTrend scTrend; + XTrend mcTrend; + XTrend lcTrend; + XTrend hcTrend; + + // + bool drawTrends; + bool drawSCTrend; + bool drawMCTrend; + bool drawLCTrend; + bool drawHCTrend; + bool manageTrends; + + // + bool HasTrend() + { + // + bool result = + HasSCTrend() || + HasMCTrend() || + HasLCTrend() || + HasHCTrend(); + + // + return result; + } + + // + bool HasSCTrend() + { + return scTrend.IsValid() && + scTrend.HasTrend(); + } + + // + bool HasMCTrend() + { + return mcTrend.IsValid() && + mcTrend.HasTrend(); + } + + // + bool HasLCTrend() + { + return lcTrend.IsValid() && + lcTrend.HasTrend(); + } + + // + bool HasHCTrend() + { + return hcTrend.IsValid() && + hcTrend.HasTrend(); + } + + // + void DrawTrends() + { + // + if (!drawTrends || !HasTrend()) + { + return; + } + + // + // SC ... + if (drawSCTrend && HasSCTrend()) + { + poiDrawer.DrawTrendLine(scTrend, structureDrawConfig.drawConfig); + } + + // + // MC ... + if (drawMCTrend && HasMCTrend()) + { + poiDrawer.DrawTrendLine(mcTrend, structureDrawConfig.drawConfig); + } + + // + // LC ... + if (drawLCTrend && HasLCTrend()) + { + poiDrawer.DrawTrendLine(lcTrend, structureDrawConfig.drawConfig); + } + + // + // HC ... + if (drawHCTrend && HasHCTrend()) + { + poiDrawer.DrawTrendLine(hcTrend, structureDrawConfig.drawConfig); + } + } + + // + void ManageTrends(XOHCL &bar) + { + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XTrend tmpTrend; + + // + // SC ... + tmpTrend.Clean(); + has = fimaParser.HasSCTrend(tmpTrend, bar.Index()); + if (has) + { + scTrend = tmpTrend; + } + + // + // MC ... + tmpTrend.Clean(); + has = fimaParser.HasMCTrend(tmpTrend, bar.Index()); + if (has) + { + mcTrend = tmpTrend; + } + + // + // LC ... + tmpTrend.Clean(); + has = fimaParser.HasLCTrend(tmpTrend, bar.Index()); + if (has) + { + lcTrend = tmpTrend; + } + + // + // HC ... + tmpTrend.Clean(); + has = fimaParser.HasHCTrend(tmpTrend, bar.Index()); + if (has) + { + hcTrend = tmpTrend; + } + + // + DrawTrends(); + + // + // Cleanup ... + tmpTrend.Clean(); + } + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = true; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = false; + + // + XBoxZone tmpZone; + string provider = NULL; + ENUM_X_DIRECTION tmpDir; + + // + bool signaller1HasSignal = false; + bool signaller2HasSignal = false; + bool signaller3HasSignal = false; + bool signaller4HasSignal = false; + + // + // Validator Flags ... + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = false; + bool drawMarketStructureAnalysis = false; + bool drawMarketStructureOrderFlow = false; + XPOIDrawConfig iDrawConfig; + + // + drawLeg = false; + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Signal Detection Flags ... + + // + // Signaller 1 ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += "1"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + if (useSignaller2) + { + // + signaller2HasSignal = Strategy2HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller2HasSignal) + { + // + provider += "2"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + if (useSignaller3) + { + // + signaller3HasSignal = Strategy3HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller3HasSignal) + { + // + provider += "3"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + if (useSignaller4) + { + // + signaller4HasSignal = Strategy4HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller4HasSignal) + { + // + provider += "4"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal; + + // + // Signal Validating ... + + // + // Validate Signals by Order Flow ... + if (result && validateByOrderFlow) + { + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + + // + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Prepare Draw Config ... + iDrawConfig = structureDrawConfig.drawConfig; + iDrawConfig.zonesWidth = 3; + iDrawConfig.zonesStyle = STYLE_DASH; + iDrawConfig.bullishColor = clrYellow; + iDrawConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (drawZone) + { + poiDrawer.DrawZone(zone, iDrawConfig); + } + + // + // Draw Market Structure ... + + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } + } + + // + // Other Drawing Materials ... + Print("Signaller Providers: ", provider); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + tmpZone.Clean(); + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + return result; + } + + // + // Reading Conditions ... + int pullBackStartBar = -1; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + zone, + dir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(dir); + bool isPullbackBearish = isPullBack && + IsXBearish(dir); + if (isPullBack) + { + pullBackStartBar = zone.FromIndex(); + } + + // + // Reading HK Band ... + + // + double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index()); + double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index()); + int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH); + + // + // Reading PV Requirements ... + + // + int lastPeakOverLastIDX = -1; + int lastValeUnderLastIDX = -1; + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + int samePeaks = fimaParser.CountSamePeaks(pBar.Index()); + int sameVales = fimaParser.CountSameVales(pBar.Index()); + fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); + + // + // Reading pBar Patterns ... + XOHCL _tmpBar; + XPivot _tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + structureConfig.barsAnalysisConfig // + ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + if (hasSupport) + { + hasSupport = pBarPatterns.GetSupport(_tmpBar, _tmpPivot, _support); + } + if (hasResistance) + { + hasResistance = pBarPatterns.GetResistance(_tmpBar, _tmpPivot, _resistance); + } + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + + // + // Try To Find Affected Zone ... + + // + // Collecting Zones ... + XBoxZone zones[]; + XBoxZone affectedZones[]; + XBoxZone affectedZonesBullish[]; + XBoxZone affectedZonesBearish[]; + int zonesCount = poiDetector.CollectZones( + pBar, + zones, // + 5, // Zones Loopback ... + 3 // Zones Validation Length ... + // Required Zones ... + // Loopback ... + ); + int affectedZonesCount = ExtractAffectedZones( + pBar, + zones, + affectedZones // + ); + int affectedZonesBullishCount = ExtractByDirection( + affectedZonesBullish, + affectedZones, + X_DIRECTION_BULLISH // + ); + int affectedZonesBearishCount = ExtractByDirection( + affectedZonesBearish, + affectedZones, + X_DIRECTION_BEARISH // + ); + + // + int insideBullishIDX = -1; + int insideBearishIDX = -1; + bool hasBullishInside = + pBar.IsBullish() && + HasInside( + insideBullishIDX, + pBar, + affectedZonesBullish // + ); + bool hasBearishInside = + pBar.IsBearish() && + HasInside( + insideBearishIDX, + pBar, + affectedZonesBearish // + ); + + // + // Detecting Boundary Trend ... + XTrend boundaryTrend; + double boundaryMin = fimaParser.GetBoundaryMin(pBar.Index()); + double boundaryMax = fimaParser.GetBoundaryMax(pBar.Index()); + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // Do ... + + // + isBullish = + // + hasBullishInside && + isPullbackBullish && + isPBarHasBullishPatterns && + fimaParser.IsSARBullish(pBar.Index()) && + (pVale >= affectedZonesBullish[insideBullishIDX].lower && + pVale <= affectedZonesBullish[insideBullishIDX].upper) + // + ; + + // + isBearish = + // + hasBearishInside && + isPullbackBearish && + isPBarHasBearishPatterns && + fimaParser.IsSARBearish(pBar.Index()) && + (pPeak >= affectedZonesBearish[insideBearishIDX].lower && + pPeak <= affectedZonesBearish[insideBearishIDX].upper) + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + if (isBullish) + { + zone = affectedZonesBullish[insideBullishIDX]; + } + else + { + zone = affectedZonesBearish[insideBearishIDX]; + } + + // + result = zone.IsValid(); + + // + // Zone Validations ... + if (result) + { + // + if (boundaryTrend.IsValid()) + { + poiDrawer.DrawTrendLine(boundaryTrend, structureDrawConfig.drawConfig); + } + + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + + // + if (hasSupport) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (hasResistance) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (HasChild(affectedZones)) + { + poiDrawer.DrawZones(affectedZones, structureDrawConfig.drawConfig); + } + + // + if (NotEmptyZero(boundaryMin)) + { + // + XTrend trend; + trend.Init( + pBar.symbol, + pBar.period, + bar.time, + boundaryMin, + pBar.BeforeOn(), + boundaryMin, + pBar.NextAt() // + ); + if (trend.IsValid()) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + poiDrawer.DrawTrendLine(trend, iConfig); + + // + iConfig.Clean(); + } + + // + trend.Clean(); + } + + // + if (NotEmptyZero(boundaryMax)) + { + // + XTrend trend; + trend.Init( + pBar.symbol, + pBar.period, + bar.time, + boundaryMax, + pBar.BeforeOn(), + boundaryMax, + pBar.NextAt() // + ); + if (trend.IsValid()) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + poiDrawer.DrawTrendLine(trend, iConfig); + + // + iConfig.Clean(); + } + + // + trend.Clean(); + } + + // + DebugBreak(); + } + + // + result = zone.IsValid(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + XClean(zones); + _tmpBar.Clean(); + _support.Clean(); + _tmpPivot.Clean(); + _resistance.Clean(); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + XClean(affectedZones); + XClean(affectedZonesBullish); + XClean(affectedZonesBearish); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * Strategy 2: + * =========== + * - Works Based On PBar Patterns Focused on PinBar ... + * - Looking for a Bar Directional Pattern Happens ... + * - Validate Fast Ma Over/Under Slow ... + * - Validate P2Peak/Vale doesnt Under or Over Last (InDirectional) ... + * - Validate P2Bar Has Directional Market Strucuture Zone (OB, FVG, Support/Resistance) ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarPatterns; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + structureConfig.barsAnalysisConfig // + ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Check Boundary Trend ... + XTrend boundaryTrend; + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // Check Bar Patterns ... + + // + // Bars Sequences ... + bool hasBullishSequence = p3Bar.IsBearish() && + pBar.IsBullish(); + bool hasBearishSequence = p3Bar.IsBullish() && + pBar.IsBearish(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Check Based On LC and HC MA State ... + + // + bool isLCMABullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCMABullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isCycleMABullish = isLCMABullish && isHCMABullish; + + // + bool isLCMABearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCMABearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isCycleMABearish = isLCMABearish && isHCMABearish; + + // + // Do ... + + // + isBullish = + // + hasSupport && + isFastOverLast && + isValeUnderLast && + isCycleMABullish && + hasBullishSequence && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + hasBoundaryBullishTrend && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + hasResistance && + isPeakOverLast && + isFastUnderLast && + isCycleMABearish && + !isP2ValeOverLast && + hasBearishSequence && + isPBarCloseUnderFast && + isP2BarBearishPinned && + hasBoundaryBearishTrend && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Draws ... + if (result) + { + // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine(boundaryTrend, iConfig); + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // iConfig.Clean(); + + // + // DebugBreak(); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Strategy 3: + * =========== + * - Works Based On Breaked Support or Resistances ... + * - Looking for a Support or Resistance to Breaked ... + * - Validate Breaker Bar to Change Peak or Vale ... + * - Validate Bar Opposit Side of Breaker Bar's Shadow ... + * - Validate by Checking Market Strucutre to Has Directional Zone + * (Support for Resistance Break / Resistance for Support Break) ... + * - Validate Breaker Bar to Has Directional FVG ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + + // + bool validateByPVChanges = true; + bool validateByGapExists = true; + bool validateByBarShadows = true; + bool validateHasDirectionalZone = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XBoxZone _fvg; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + // Price Must Break Support or Resistance ... + + // + // Extract Support and Resistance ... + bool hasSupport = p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsResistance(); + if (hasSupport) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, _support); + tmpBar.Clean(); + tmpPivot.Clean(); + } + if (hasResistance) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + tmpBar.Clean(); + tmpPivot.Clean(); + } + + // + bool hasBreakedSupport = hasSupport && + pBar.close < _support.lower && + p2Bar.close > _support.lower; + bool hasBreakedResistance = hasResistance && + pBar.close > _resistance.upper && + p2Bar.close < _resistance.upper; + + // + isBullish = hasBreakedResistance; + isBearish = hasBreakedSupport; + + // + result = isBullish || isBearish; + + // + // Validate By PV Changed ... + // Breaker Bar must Change Peak or Value ... + if (result && validateByPVChanges) + { + // + bool isPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + + // + isBullish = + isBullish && + isPeakOverLast; + + // + isBearish = + isBearish && + isValeUnderLast; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Bar Shadows ... + // Breakre Bar Side Shadow must not Reached ... + if (result && validateByBarShadows) + { + // + isBullish = + isBullish && + pBar.low > p2Bar.low; + + // + isBearish = + isBearish && + pBar.high < p2Bar.high; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Has Directional Zone ... + if (result && validateHasDirectionalZone) + { + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate By Gap Exists ... + if (result && validateByGapExists) + { + // + ENUM_X_DIRECTION tmpDir; + bool hasFVG = poiDetector.HasFVG( + pBar, + tmpDir, + _fvg // + ); + + // + isBullish = + isBullish && + hasFVG && + IsXBullish(tmpDir); + + // + isBearish = + isBearish && + hasFVG && + IsXBearish(tmpDir); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Prepare Direction and Zone ... + if (result) + { + // + if (isBullish) + { + // + zone = _resistance; + zone.dir = Opposit(_resistance.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + if (isBearish) + { + // + zone = _support; + zone.dir = Opposit(_support.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + // Zone Validation Base ... + result = zone.IsValid(); + if (result) + { + // + // Validate By Trend of Zone ... + XTrend zoneTrend; + XTrend zoneToTrend; + + // + // Detecting Trends ... + result = poiDetector.HasBoundaryTrend(zone, zoneTrend, false); + result = result && + poiDetector.HasBoundaryTrend(zone, zoneToTrend, true); + + // + // Validate Trend ... + result = + result && + zone.dir == zoneTrend.dir && + zone.dir == zoneToTrend.dir; + + // + // Draw ... + if (result) + { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + + // // + // poiDrawer.DrawTrendLine(zoneTrend, iConfig); + // poiDrawer.DrawTrendLine(zoneToTrend, iConfig); + + // // + // iConfig.Clean(); + } + + // + // Cleanup ... + zoneTrend.Clean(); + zoneToTrend.Clean(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + result = zone.IsValid(); + } + + // + if (result) + { + // + if (_support.IsValid()) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (_resistance.IsValid()) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (pBarPatterns.IsValid()) + { + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + patternConfig.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Strategy 4: + * =========== + * - Works Based on Order Flow ... + * - Looking for new and Fresh Order Flow ... + * - Validate Bar is Inside Order Flow ... + * - Validate Bar has Proper Pattern ... + * - Validate Bar Based on ATR Band in two Step: + * - Step 1: Bars is Inside ATR Band (Middle) ... + * - Step 2: Trigger Bars Close Price based on ATR Band ... + * - Validate Order Flow based on Market Structure Zone ... + * - Validate Trigger Bar based on InDirectional Market Structure Zones ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateBarInsideZone = true; + bool validateByBarPatterns = true; + bool validateByXFIMABoundary = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = true; + bool validateMarketStructureHasDirectionalZone = true; + bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; + bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + // Detecting OrderFlow ... + XBoxZone oFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + p3Bar, + dir, + oFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + + // + XTrend boundaryTrend; + XTrend boundaryZoneTrend; + + // + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + double atrBandMiddle = EMPTY_VALUE; + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force Price of p2Bar is Inside Order Flow ... + if (result && validateBarInsideZone) + { + // + double orderFlowUpper = 0; + double orderFlowLower = 0; + + // + int idx = -1; + idx = GetHighest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowUpper = oFlow[idx].upper; + } + idx = GetLowest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowLower = oFlow[idx].lower; + } + + // + result = NotEmptyZero(orderFlowUpper) && + NotEmptyZero(orderFlowLower) && + orderFlowUpper > orderFlowLower && + (isBullish + ? p2Bar.low < orderFlowUpper + : p2Bar.high > orderFlowLower); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + // (bar.close > pBar.low || + // bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + // (bar.close < pBar.high || + // bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force P2Bar Place Checking based on ATR Band ... + if (result && validateByBarInsideATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); + + // + atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); + + // + isBullish = + isBullish && + NotEmptyZero(atrBandMiddle) && + p2Bar.low < atrBandMiddle; + + // + isBearish = + isBearish && + NotEmptyZero(atrBandMiddle) && + p2Bar.high > atrBandMiddle; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Place Checking based on ATR Band ... + if (result && validateByBarBasedOnATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); + + // + result = + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower) && + (isBullish + ? pBar.close > atrBandLower + : pBar.close < atrBandUpper); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // for Bullish has Support ... + // for Bearish has Resistance ... + if (result && validateMarketStructureHasDirectionalZone) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Validate Support and Resistance by Order Flow ... + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + // Check Market Strucutre Support and Resistance Validation ... + if (validateMarketStructureDirectionalZoneInsideOrderFlow) + { + // + hasSupport = + hasOFBox && + hasSupport && + ofZone.lower < _support.lower && + ofZone.upper > _support.upper; + + // + hasResistance = + hasOFBox && + hasResistance && + ofZone.lower < _resistance.lower && + ofZone.upper > _resistance.upper; + } + + // + // Validate Directional Support or Resistance Exists ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Makret Structure Has Not Indirectional Zone ... + if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + bool hasIndirectionalZone = + (isBullish && hasResistance) || + (isBearish && hasSupport); + if (hasIndirectionalZone) + { + // + // Here we Have to Validate Zone Place ... + + // + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Bullish ... + if (isBullish && hasResistance) + { + hasResistance = _resistance.lower <= tp; + } + + // + // Bearish ... + if (isBearish && hasSupport) + { + hasSupport = _support.upper >= tp; + } + } + + // + isBullish = + isBullish && + !hasResistance; + + // + isBearish = + isBearish && + !hasSupport; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate ... + result = isBullish || isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone and do Zone Based Validations ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Refine Zone ... + zone.to = bar.time; + zone.upper = MathMax(zone.upper, atrBandMiddle); + zone.lower = MathMin(zone.lower, atrBandMiddle); + + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Try to Retrieve Boundary To Trend ... + result = poiDetector.HasBoundaryTrend( + zone, + boundaryTrend, + true // + ); + + // + // Try to Retrieve Boundary Zone Trend ... + result = + result && + poiDetector.HasBoundaryTrend( + zone, + boundaryZoneTrend, + false // + ); + + // + // Check and Validate Trend Direction ... + result = + result && + zone.dir == boundaryTrend.dir && + zone.dir == boundaryZoneTrend.dir; + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + } + } + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + XTarget iTarget; + + // + // Calculate Requirements ... + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // High Risk Target is Used to Protect In Profit Positiions + // from Reversal Patterns ... + double highRiskR2r = (defaultSignalR2R / 5) * 4; + double highRiskReward = highRiskR2r * risk; + double highRiskTP = isBullish + ? entry + highRiskReward + : entry - highRiskReward; + iTarget.Clean(); + iTarget.actingDistance = 5; + iTarget.doRFOnEntry = true; + iTarget.target = highRiskTP; + iTarget.volumeMultiplier = 0.8; + // AddRef(iTarget, targets); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(oFlow); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); + boundaryZoneTrend.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 3.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 3.mq5 new file mode 100644 index 0000000..6283fb8 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 3.mq5 @@ -0,0 +1,3780 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure ... + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + manageZones = true; + manageIZones = true; + manageTrends = false; + manageOrderFlow = true; + + // + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Manage ... + Manage(iBar); + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + + // + // Remove TP if in Profit SL ... + iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + has = + (positions[i].IsBullish() && HasResistance()) + ? (iGuard.sl >= iValue && + positions[i].tp < resistance.lower) + : (positions[i].IsBearish() && HasSupport()) + ? (iGuard.sl <= iValue && + positions[i].tp > support.upper) + : false; + if (has) + { + // + iGuard.Clean(); + iGuard.force = false; + iGuard.tp = positions[i].IsBullish() + ? resistance.lower + : support.upper; + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + } + } + } + } + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + void Manage(XOHCL &bar) + { + // + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + has = bar.GetPreviousBar(pBar); + has = has && + pBar.GetPreviousBar(p2Bar); + has = has && + p2Bar.GetPreviousBar(p3Bar); + if (!has) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + ManageTrends(bar); + ManageZones(p2Bar); + ManageIZones(p2Bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + // Private ... + private: + // + // Props ... + + // + // Order Flow ... + + // + bool drawOrderFlow; + XBoxZone orderFlow[]; + bool manageOrderFlow; + ENUM_X_DIRECTION orderFlowDir; + + // + bool HasOrderFlow() + { + // + return HasChild(orderFlow) && + HasDirection(orderFlowDir); + } + + // + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + // + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + + // + bool GetOrderFlowBoundary( + double &upper, + double &lower // + ) + { + // + bool result = false; + + // + // Prepare ... + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + + // + // Validate ... + result = HasOrderFlow(); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Upper ... + idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + upper = orderFlow[idx].upper; + } + + // + // Lower ... + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + lower = orderFlow[idx].lower; + } + + // + result = NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + // Cleanup ... + if (!result) + { + // + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + } + + // + return result; + } + + // + bool ValidateOrderFlow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasOrderFlow(); + if (!result) + { + return result; + } + + // + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + result = GetOrderFlowBoundary(upper, lower); + result = result && + HasBullishOrderFlow() + ? bar.low > lower + : bar.high < upper; + + // + return result; + } + + // + void DrawOrderFlow() + { + // + if (!drawOrderFlow || !HasOrderFlow()) + { + return; + } + + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); + } + + // + void ManageOrderFlow(XOHCL &bar) + { + // + // Validate Exists ... + if (HasOrderFlow()) + { + // + if (!ValidateOrderFlow(bar)) + { + // + // Invalidate OrderFlow ... + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + } + + // + // Detect New ... + if (!HasOrderFlow()) + { + // + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // patternConfig.Default(); + // patternConfig.supportAndResistanceLoopbackLength = 21; + // patternConfig.supportAndResistanceValidationLength = 7; + + // + poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + } + + // + // Update Exists ... + if (HasOrderFlow()) + { + // + // Update to Times ... + UpdateToTime(orderFlow, TimeCurrent()); + + // + DrawOrderFlow(); + } + } + + // + // Zone ... + + // + XBoxZone support; + XBoxZone resistance; + bool drawZones; + bool drawSupport; + bool manageZones; + bool drawResistance; + + // + bool HasZones() + { + return HasSupport() || + HasResistance(); + } + + // + bool HasSupport() + { + return support.IsValid(); + } + + // + bool HasResistance() + { + return resistance.IsValid(); + } + + // + bool ValidateZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; + } + + // + void DrawZones() + { + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } + } + + // + void ManageZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + // + if (support.IsValid()) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + // + if (resistance.IsValid()) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASup"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + XBoxZone iSupport; + XBoxZone iResistance; + bool drawIZones; + bool drawISupport; + bool manageIZones; + bool drawIResistance; + + // + bool HasIZones() + { + // + return HasISupport() || + HasIResistance(); + } + + // + bool HasISupport() + { + return iSupport.IsValid(); + } + + // + bool HasIResistance() + { + return iResistance.IsValid(); + } + + // + void DrawIZones() + { + // + if (!drawIZones || !HasIZones()) + { + return; + } + + // + if (drawISupport && HasISupport()) + { + poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig); + } + + // + if (drawIResistance && HasIResistance()) + { + poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig); + } + } + + // + bool ValidateIZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasIZones(); + if (!result) + { + return result; + } + + // + + // + // Support ... + bool hasSupport = HasISupport(); + if (hasSupport) + { + // + result = bar.close > iSupport.lower && + !IsBreaked(iSupport, X_PRICE_CLOSE); + if (!result) + { + // + iSupport.breakAt = bar.time; + iSupport.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasIResistance(); + if (hasResistance) + { + // + result = bar.close < iResistance.upper && + !IsBreaked(iResistance, X_PRICE_CLOSE); + if (!result) + { + // + iResistance.breakAt = bar.time; + iResistance.Clean(); + } + } + + // + result = + (hasSupport && !HasISupport()) || + (hasResistance && !HasIResistance()); + + // + return result; + } + + // + void ManageIZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasIZones()) + { + // + if (!ValidateIZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(iSupport.breakAt)) + { + iSupport.Clean(); + } + + // + // Resistance ... + if (IsXValid(iResistance.breakAt)) + { + iResistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasIZones()) + { + // + if (HasISupport()) + { + // + iSupport.to = bar.time; + iSupport.type = "XFIMAISup"; + } + + // + if (HasIResistance()) + { + // + iResistance.to = bar.time; + iResistance.type = "XFIMAIRes"; + } + + // + DrawIZones(); + } + } + + // + // Trends ... + + // + XTrend scTrend; + XTrend mcTrend; + XTrend lcTrend; + XTrend hcTrend; + + // + bool drawTrends; + bool drawSCTrend; + bool drawMCTrend; + bool drawLCTrend; + bool drawHCTrend; + bool manageTrends; + + // + bool HasTrend() + { + // + bool result = + HasSCTrend() || + HasMCTrend() || + HasLCTrend() || + HasHCTrend(); + + // + return result; + } + + // + bool HasSCTrend() + { + return scTrend.IsValid() && + scTrend.HasTrend(); + } + + // + bool HasMCTrend() + { + return mcTrend.IsValid() && + mcTrend.HasTrend(); + } + + // + bool HasLCTrend() + { + return lcTrend.IsValid() && + lcTrend.HasTrend(); + } + + // + bool HasHCTrend() + { + return hcTrend.IsValid() && + hcTrend.HasTrend(); + } + + // + void DrawTrends() + { + // + if (!drawTrends || !HasTrend()) + { + return; + } + + // + // SC ... + if (drawSCTrend && HasSCTrend()) + { + poiDrawer.DrawTrendLine(scTrend, structureDrawConfig.drawConfig); + } + + // + // MC ... + if (drawMCTrend && HasMCTrend()) + { + poiDrawer.DrawTrendLine(mcTrend, structureDrawConfig.drawConfig); + } + + // + // LC ... + if (drawLCTrend && HasLCTrend()) + { + poiDrawer.DrawTrendLine(lcTrend, structureDrawConfig.drawConfig); + } + + // + // HC ... + if (drawHCTrend && HasHCTrend()) + { + poiDrawer.DrawTrendLine(hcTrend, structureDrawConfig.drawConfig); + } + } + + // + void ManageTrends(XOHCL &bar) + { + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XTrend tmpTrend; + + // + // SC ... + tmpTrend.Clean(); + has = fimaParser.HasSCTrend(tmpTrend, bar.Index()); + if (has) + { + scTrend = tmpTrend; + } + + // + // MC ... + tmpTrend.Clean(); + has = fimaParser.HasMCTrend(tmpTrend, bar.Index()); + if (has) + { + mcTrend = tmpTrend; + } + + // + // LC ... + tmpTrend.Clean(); + has = fimaParser.HasLCTrend(tmpTrend, bar.Index()); + if (has) + { + lcTrend = tmpTrend; + } + + // + // HC ... + tmpTrend.Clean(); + has = fimaParser.HasHCTrend(tmpTrend, bar.Index()); + if (has) + { + hcTrend = tmpTrend; + } + + // + DrawTrends(); + + // + // Cleanup ... + tmpTrend.Clean(); + } + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = true; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = false; + + // + XBoxZone tmpZone; + string provider = NULL; + ENUM_X_DIRECTION tmpDir; + + // + bool signaller1HasSignal = false; + bool signaller2HasSignal = false; + bool signaller3HasSignal = false; + bool signaller4HasSignal = false; + + // + // Validator Flags ... + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = false; + bool drawMarketStructureAnalysis = false; + bool drawMarketStructureOrderFlow = false; + XPOIDrawConfig iDrawConfig; + + // + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Signal Detection Flags ... + + // + // Signaller 1 ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += "1"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + if (useSignaller2) + { + // + signaller2HasSignal = Strategy2HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller2HasSignal) + { + // + provider += "2"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + if (useSignaller3) + { + // + signaller3HasSignal = Strategy3HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller3HasSignal) + { + // + provider += "3"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + if (useSignaller4) + { + // + signaller4HasSignal = Strategy4HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller4HasSignal) + { + // + provider += "4"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal; + + // + // Signal Validating ... + + // + // Validate Signals by Order Flow ... + if (result && validateByOrderFlow) + { + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + + // + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Prepare Draw Config ... + iDrawConfig = structureDrawConfig.drawConfig; + iDrawConfig.zonesWidth = 3; + iDrawConfig.zonesStyle = STYLE_DASH; + iDrawConfig.bullishColor = clrYellow; + iDrawConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (drawZone) + { + poiDrawer.DrawZone(zone, iDrawConfig); + } + + // + // Draw Market Structure ... + + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } + } + + // + // Other Drawing Materials ... + Print("Signaller Providers: ", provider); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + tmpZone.Clean(); + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone atrBox; + XBoxZone zones[]; + XBoxZone tmpZone; + XBoxZone scPVZone; + XBoxZone mcPVZone; + XBoxZone lcPVZone; + XBoxZone hcPVZone; + XBoxZone tmpZones[]; + XBoxZone pinBarZone; + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone affectedZone; + XTrend pinBarZoneTrend; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION tmpDir; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysis p3BarPatterns; + XPatternAnalysisConfig iPatternsConfig; + + // + // Reading Bars ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading Bar Patterns ... + iPatternsConfig.Default(); + iPatternsConfig.FullPattern(); + result = + result && + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p3Bar, + p3BarPatterns, + iPatternsConfig // + ); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } + + // + // Detect Directional Candlestic Patterns ... + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isP2BarHasBullishPatterns = + (bar.close > p2Bar.low || + bar.open > p2Bar.low) && + ( + // + p2BarPatterns.IsPinned(X_DIRECTION_BULLISH) || + p2BarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + p2BarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + p2BarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + p2BarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isP3BarHasBullishPatterns = + (bar.close > p3Bar.low || + bar.open > p3Bar.low) && + ( + // + p3BarPatterns.IsPinned(X_DIRECTION_BULLISH) || + p3BarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + p3BarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + p3BarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + p3BarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + bool isP2BarHasBearishPatterns = + (bar.close < p2Bar.high || + bar.open < p2Bar.high) && + ( + // + p2BarPatterns.IsPinned(X_DIRECTION_BEARISH) || + p2BarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + p2BarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + p2BarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + p2BarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + bool isP3BarHasBearishPatterns = + (bar.close < p3Bar.high || + bar.open < p3Bar.high) && + ( + // + p3BarPatterns.IsPinned(X_DIRECTION_BEARISH) || + p3BarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + p3BarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + p3BarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + p3BarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Checking Support and Resistances ... + + // + // Support ... + bool hasSupport = pBarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = pBarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = p2BarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + hasSupport = p3BarPatterns.IsSupport(); + if (hasSupport) + { + // + hasSupport = p3BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + if (hasSupport) + { + AddIfNotExists(tmpZone, supports); + } + } + + // + // Resistance ... + bool hasResistance = pBarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = pBarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = p2BarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + hasResistance = p3BarPatterns.IsResistance(); + if (hasResistance) + { + // + hasResistance = p3BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + if (hasResistance) + { + AddIfNotExists(tmpZone, resistances); + } + } + + // + // Collecting Zones ... + + // + int collectedZonesCount = poiDetector.DetectZones( + bar, + zones, + true, // Validated Zones ... + false, // Remove Used Zones ... + false, // Contains Order Blocks ... + true, // Contains Fair Value Gaps ... + true, // Contains Supports ... + true, // Contains Resistances ... + X_DIRECTION_NONE, // For Dir (Contains All Direction Zones) ... + X_SORT_BY_DATE, // Sort By ... + X_DIRECTION_BEARISH, // Sort Dir ... + 3, // Zones Loopback ... + 3, // Zones Validation Length ... + 0, // Count (All Zones) ... + 100 // Loop back for Detection ... + ); + bool hasCollectedZones = IsValidSize(collectedZonesCount) && + collectedZonesCount > 1; + int affectedZonesCount = 0; + bool hasAffectedZone = false; + int collectedZonesBullishCount = 0; + int collectedZonesBearishCount = 0; + bool hasBullishAffectedZone = false; + bool hasBearishAffectedZone = false; + bool hasBullishCollectedZones = false; + bool hasBearishCollectedZones = false; + if (hasCollectedZones) + { + // + // Bullish ... + XClean(tmpZones); + collectedZonesBullishCount = ExtractByDirection(tmpZones, zones, X_DIRECTION_BULLISH); + hasBullishCollectedZones = IsValidSize(collectedZonesBullishCount); + + // + // Bearish ... + XClean(tmpZones); + collectedZonesBearishCount = ExtractByDirection(tmpZones, zones, X_DIRECTION_BEARISH); + hasBearishCollectedZones = IsValidSize(collectedZonesBearishCount); + + // + // Extract Affected Zones ... + XClean(tmpZones); + int affectedZonesCount = ExtractAffectedZones(p2Bar, zones, tmpZones); + int idx = GetYoungest(tmpZones); + if (IsValidIndex(idx)) + { + affectedZone = tmpZones[idx]; + } + hasAffectedZone = affectedZone.IsValid(); + hasBullishAffectedZone = hasAffectedZone && affectedZone.IsBullish(); + hasBearishAffectedZone = hasAffectedZone && affectedZone.IsBearish(); + } + + // + // Reading Cycle PVS ... + bool hasSCPV = poiDetector.GetSCZone(pBar, scPVZone); + bool hasMCPV = poiDetector.GetMCZone(pBar, mcPVZone); + bool hasLCPV = poiDetector.GetLCZone(pBar, lcPVZone); + bool hasHCPV = poiDetector.GetHCZone(pBar, hcPVZone); + bool isCyclePVBullish = + hasMCPV && mcPVZone.IsBullish() && + hasLCPV && lcPVZone.IsBullish() && + hasHCPV && hcPVZone.IsBullish(); + bool isCyclePVBearish = + hasMCPV && mcPVZone.IsBearish() && + hasLCPV && lcPVZone.IsBearish() && + hasHCPV && hcPVZone.IsBearish(); + + // + // Validating Market Direction ... + // by Checking HC and LC States ... + + // + bool isLCBullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCBullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isLCHigherLow = + (fimaParser.IsLCHigherLow(pBar.Index()) || + fimaParser.IsLCHigherLow(p2Bar.Index()) || + fimaParser.IsLCHigherLow(p3Bar.Index())); + bool isCyclesBullish = + isLCBullish && + isHCBullish && + isLCHigherLow; + + // + bool isLCBearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCBearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isLCLowerHigh = + (fimaParser.IsLCLowerHigh(pBar.Index()) || + fimaParser.IsLCLowerHigh(p2Bar.Index()) || + fimaParser.IsLCLowerHigh(p3Bar.Index())); + bool isCyclesBearish = + isLCBearish && + isHCBearish && + isLCLowerHigh; + + // + // Looking For a Pin Bar in P2Bar ... + bool isP2BarIsPinBar = poiDetector.IsPinnedBar( + p2Bar, + tmpDir, + 4, // Shadow Multiplier ... + 4, // Minimum Range Multiplier ... + true // Force Pin Bar Direction ... + ); + if (isP2BarIsPinBar) + { + // + isP2BarIsPinBar = ToBox( + p2Bar, + pinBarZone, + tmpDir, + X_BAR_PATTERN_PINNED // + ); + if (isP2BarIsPinBar) + { + // + pinBarZone.to = bar.time; + isP2BarIsPinBar = poiDetector.HasBoundaryTrend( + pinBarZone, + pinBarZoneTrend, + false // + ); + isP2BarIsPinBar = + isP2BarIsPinBar && + tmpDir == pinBarZoneTrend.dir; + } + } + bool isP2BarPinnedBullish = isP2BarIsPinBar && IsXBullish(tmpDir); + bool isP2BarPinnedBearish = isP2BarIsPinBar && IsXBearish(tmpDir); + + // + // Checking ATR Box ... + bool hasATRBox = fimaParser.GetATRBox( + atrBox, + bar.Index() // + ); + bool hasATRBoxBullish = hasATRBox && atrBox.IsBullish(); + bool hasATRBoxBearish = hasATRBox && atrBox.IsBearish(); + + // + // Checking Double Patterns ... + ENUM_X_DIRECTION iDBDir; + XPatternAnalysis iPatterns; + XPatternAnalysis iPPatterns; + ENUM_X_BAR_PATTERN doublePatterns[]; + GetCandlestickPatterns(doublePatterns); + bool hasDoublePatterns = poiDetector.HasDoublePatterns( + pBar, + iDBDir, + iPatterns, + iPPatterns, + doublePatterns, + iPatternsConfig, + 5 // + ); + bool hasBullishDoublePatterns = hasDoublePatterns && IsXBullish(iDBDir); + bool hasBearishDoublePatterns = hasDoublePatterns && IsXBearish(iDBDir); + + // + isBullish = + // + hasSupport && + hasResistance && + isCyclesBullish && + hasATRBoxBullish && + isCyclePVBullish && + isP2BarPinnedBullish && + hasBullishAffectedZone && + isPBarHasBullishPatterns && + hasBullishCollectedZones && + isP2BarHasBullishPatterns && + collectedZonesBullishCount > collectedZonesBearishCount && + true + // + ; + + // + isBearish = + // + hasSupport && + hasResistance && + isCyclesBearish && + hasATRBoxBearish && + isCyclePVBearish && + isP2BarPinnedBearish && + hasBearishAffectedZone && + isPBarHasBearishPatterns && + hasBearishCollectedZones && + isP2BarHasBearishPatterns && + collectedZonesBearishCount > collectedZonesBullishCount && + true + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + zone = pinBarZone; + + // + result = zone.IsValid(); + } + + // + // Draws ... + if (result) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + XPatternAnalysisDrawConfig iPatternsConfig = structureDrawConfig.barAnalysisDrawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + // poiDrawer.DrawZone(scPVZone, iConfig); + // poiDrawer.DrawZone(mcPVZone, iConfig); + // poiDrawer.DrawZone(lcPVZone, iConfig); + // poiDrawer.DrawZone(hcPVZone, iConfig); + + // + poiDrawer.DrawPatternAnalysis(pBarPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(p2BarPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(p3BarPatterns, iPatternsConfig); + + // + poiDrawer.DrawZone(pinBarZone, iConfig); + poiDrawer.DrawZone(affectedZone, iConfig); + poiDrawer.DrawTrendLine(pinBarZoneTrend, iConfig); + + // + // poiDrawer.DrawZones(zones, iConfig); + poiDrawer.DrawZones(supports, iConfig); + poiDrawer.DrawZones(resistances, iConfig); + + // + if (hasATRBox) + { + poiDrawer.DrawZone(atrBox, iConfig); + } + + // + if (hasDoublePatterns) + { + // + poiDrawer.DrawPatternAnalysis(iPatterns, iPatternsConfig); + poiDrawer.DrawPatternAnalysis(iPPatterns, iPatternsConfig); + } + + // + iConfig.Clean(); + iPatternsConfig.Clean(); + + // + DebugBreak(); + + // // + // result = false; + // isBullish = false; + // isBearish = false; + // zone.Clean(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(zones); + tmpBar.Clean(); + tmpZone.Clean(); + XClean(supports); + XClean(tmpZones); + scPVZone.Clean(); + mcPVZone.Clean(); + lcPVZone.Clean(); + hcPVZone.Clean(); + tmpPivot.Clean(); + pinBarZone.Clean(); + XClean(resistances); + affectedZone.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + pinBarZoneTrend.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * Strategy 2: + * =========== + * - Works Based On PBar Patterns Focused on PinBar ... + * - Looking for a Bar Directional Pattern Happens ... + * - Validate Fast Ma Over/Under Slow ... + * - Validate P2Peak/Vale doesnt Under or Over Last (InDirectional) ... + * - Validate P2Bar Has Directional Market Strucuture Zone (OB, FVG, Support/Resistance) ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarPatterns; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + structureConfig.barsAnalysisConfig // + ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Check Boundary Trend ... + XTrend boundaryTrend; + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // Check Bar Patterns ... + + // + // Bars Sequences ... + bool hasBullishSequence = p3Bar.IsBearish() && + pBar.IsBullish(); + bool hasBearishSequence = p3Bar.IsBullish() && + pBar.IsBearish(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Check Based On LC and HC MA State ... + + // + bool isLCMABullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCMABullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isCycleMABullish = isLCMABullish && isHCMABullish; + + // + bool isLCMABearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCMABearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isCycleMABearish = isLCMABearish && isHCMABearish; + + // + // Do ... + + // + isBullish = + // + hasSupport && + isFastOverLast && + isValeUnderLast && + isCycleMABullish && + hasBullishSequence && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + hasBoundaryBullishTrend && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + hasResistance && + isPeakOverLast && + isFastUnderLast && + isCycleMABearish && + !isP2ValeOverLast && + hasBearishSequence && + isPBarCloseUnderFast && + isP2BarBearishPinned && + hasBoundaryBearishTrend && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Draws ... + if (result) + { + // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine(boundaryTrend, iConfig); + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // iConfig.Clean(); + + // + // DebugBreak(); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Strategy 3: + * =========== + * - Works Based On Breaked Support or Resistances ... + * - Looking for a Support or Resistance to Breaked ... + * - Validate Breaker Bar to Change Peak or Vale ... + * - Validate Bar Opposit Side of Breaker Bar's Shadow ... + * - Validate by Checking Market Strucutre to Has Directional Zone + * (Support for Resistance Break / Resistance for Support Break) ... + * - Validate Breaker Bar to Has Directional FVG ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + + // + bool validateByPVChanges = true; + bool validateByGapExists = true; + bool validateByBarShadows = true; + bool validateHasDirectionalZone = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XBoxZone _fvg; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + // Price Must Break Support or Resistance ... + + // + // Extract Support and Resistance ... + bool hasSupport = p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsResistance(); + if (hasSupport) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, _support); + tmpBar.Clean(); + tmpPivot.Clean(); + } + if (hasResistance) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + tmpBar.Clean(); + tmpPivot.Clean(); + } + + // + bool hasBreakedSupport = hasSupport && + pBar.close < _support.lower && + p2Bar.close > _support.lower; + bool hasBreakedResistance = hasResistance && + pBar.close > _resistance.upper && + p2Bar.close < _resistance.upper; + + // + isBullish = hasBreakedResistance; + isBearish = hasBreakedSupport; + + // + result = isBullish || isBearish; + + // + // Validate By PV Changed ... + // Breaker Bar must Change Peak or Value ... + if (result && validateByPVChanges) + { + // + bool isPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + + // + isBullish = + isBullish && + isPeakOverLast; + + // + isBearish = + isBearish && + isValeUnderLast; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Bar Shadows ... + // Breakre Bar Side Shadow must not Reached ... + if (result && validateByBarShadows) + { + // + isBullish = + isBullish && + pBar.low > p2Bar.low; + + // + isBearish = + isBearish && + pBar.high < p2Bar.high; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Has Directional Zone ... + if (result && validateHasDirectionalZone) + { + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate By Gap Exists ... + if (result && validateByGapExists) + { + // + ENUM_X_DIRECTION tmpDir; + bool hasFVG = poiDetector.HasFVG( + pBar, + tmpDir, + _fvg // + ); + + // + isBullish = + isBullish && + hasFVG && + IsXBullish(tmpDir); + + // + isBearish = + isBearish && + hasFVG && + IsXBearish(tmpDir); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Prepare Direction and Zone ... + if (result) + { + // + if (isBullish) + { + // + zone = _resistance; + zone.dir = Opposit(_resistance.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + if (isBearish) + { + // + zone = _support; + zone.dir = Opposit(_support.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + // Zone Validation Base ... + result = zone.IsValid(); + if (result) + { + // + // Validate By Trend of Zone ... + XTrend zoneTrend; + XTrend zoneToTrend; + + // + // Detecting Trends ... + result = poiDetector.HasBoundaryTrend(zone, zoneTrend, false); + result = result && + poiDetector.HasBoundaryTrend(zone, zoneToTrend, true); + + // + // Validate Trend ... + result = + result && + zone.dir == zoneTrend.dir && + zone.dir == zoneToTrend.dir; + + // + // Draw ... + if (result) + { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + + // // + // poiDrawer.DrawTrendLine(zoneTrend, iConfig); + // poiDrawer.DrawTrendLine(zoneToTrend, iConfig); + + // // + // iConfig.Clean(); + } + + // + // Cleanup ... + zoneTrend.Clean(); + zoneToTrend.Clean(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + result = zone.IsValid(); + } + + // + if (result) + { + // + if (_support.IsValid()) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (_resistance.IsValid()) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (pBarPatterns.IsValid()) + { + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + patternConfig.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Strategy 4: + * =========== + * - Works Based on Order Flow ... + * - Looking for new and Fresh Order Flow ... + * - Validate Bar is Inside Order Flow ... + * - Validate Bar has Proper Pattern ... + * - Validate Bar Based on ATR Band in two Step: + * - Step 1: Bars is Inside ATR Band (Middle) ... + * - Step 2: Trigger Bars Close Price based on ATR Band ... + * - Validate Order Flow based on Market Structure Zone ... + * - Validate Trigger Bar based on InDirectional Market Structure Zones ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateBarInsideZone = true; + bool validateByBarPatterns = true; + bool validateByXFIMABoundary = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = true; + bool validateMarketStructureHasDirectionalZone = true; + bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; + bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + // Detecting OrderFlow ... + XBoxZone oFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + p3Bar, + dir, + oFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + + // + XTrend boundaryTrend; + XTrend boundaryZoneTrend; + + // + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + double atrBandMiddle = EMPTY_VALUE; + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force Price of p2Bar is Inside Order Flow ... + if (result && validateBarInsideZone) + { + // + double orderFlowUpper = 0; + double orderFlowLower = 0; + + // + int idx = -1; + idx = GetHighest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowUpper = oFlow[idx].upper; + } + idx = GetLowest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowLower = oFlow[idx].lower; + } + + // + result = NotEmptyZero(orderFlowUpper) && + NotEmptyZero(orderFlowLower) && + orderFlowUpper > orderFlowLower && + (isBullish + ? p2Bar.low < orderFlowUpper + : p2Bar.high > orderFlowLower); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + // (bar.close > pBar.low || + // bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + // (bar.close < pBar.high || + // bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force P2Bar Place Checking based on ATR Band ... + if (result && validateByBarInsideATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); + + // + atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); + + // + isBullish = + isBullish && + NotEmptyZero(atrBandMiddle) && + p2Bar.low < atrBandMiddle; + + // + isBearish = + isBearish && + NotEmptyZero(atrBandMiddle) && + p2Bar.high > atrBandMiddle; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Place Checking based on ATR Band ... + if (result && validateByBarBasedOnATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); + + // + result = + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower) && + (isBullish + ? pBar.close > atrBandLower + : pBar.close < atrBandUpper); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // for Bullish has Support ... + // for Bearish has Resistance ... + if (result && validateMarketStructureHasDirectionalZone) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Validate Support and Resistance by Order Flow ... + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + // Check Market Strucutre Support and Resistance Validation ... + if (validateMarketStructureDirectionalZoneInsideOrderFlow) + { + // + hasSupport = + hasOFBox && + hasSupport && + ofZone.lower < _support.lower && + ofZone.upper > _support.upper; + + // + hasResistance = + hasOFBox && + hasResistance && + ofZone.lower < _resistance.lower && + ofZone.upper > _resistance.upper; + } + + // + // Validate Directional Support or Resistance Exists ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Makret Structure Has Not Indirectional Zone ... + if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + bool hasIndirectionalZone = + (isBullish && hasResistance) || + (isBearish && hasSupport); + if (hasIndirectionalZone) + { + // + // Here we Have to Validate Zone Place ... + + // + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Bullish ... + if (isBullish && hasResistance) + { + hasResistance = _resistance.lower <= tp; + } + + // + // Bearish ... + if (isBearish && hasSupport) + { + hasSupport = _support.upper >= tp; + } + } + + // + isBullish = + isBullish && + !hasResistance; + + // + isBearish = + isBearish && + !hasSupport; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate ... + result = isBullish || isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone and do Zone Based Validations ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Refine Zone ... + zone.to = bar.time; + zone.upper = MathMax(zone.upper, atrBandMiddle); + zone.lower = MathMin(zone.lower, atrBandMiddle); + + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Try to Retrieve Boundary To Trend ... + result = poiDetector.HasBoundaryTrend( + zone, + boundaryTrend, + true // + ); + + // + // Try to Retrieve Boundary Zone Trend ... + result = + result && + poiDetector.HasBoundaryTrend( + zone, + boundaryZoneTrend, + false // + ); + + // + // Check and Validate Trend Direction ... + result = + result && + zone.dir == boundaryTrend.dir && + zone.dir == boundaryZoneTrend.dir; + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + } + } + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + XTarget iTarget; + + // + // Calculate Requirements ... + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // High Risk Target is Used to Protect In Profit Positiions + // from Reversal Patterns ... + double highRiskR2r = (defaultSignalR2R / 5) * 4; + double highRiskReward = highRiskR2r * risk; + double highRiskTP = isBullish + ? entry + highRiskReward + : entry - highRiskReward; + iTarget.Clean(); + iTarget.actingDistance = 5; + iTarget.doRFOnEntry = true; + iTarget.target = highRiskTP; + iTarget.volumeMultiplier = 0.8; + // AddRef(iTarget, targets); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(oFlow); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); + boundaryZoneTrend.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 new file mode 100644 index 0000000..65f7353 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 @@ -0,0 +1,3485 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure ... + drawLeg = true; + drawZones = true; + drawIZones = true; + drawTrends = true; + drawSCTrend = true; + drawMCTrend = true; + drawLCTrend = true; + drawHCTrend = true; + drawSupport = true; + drawISupport = true; + drawOrderFlow = true; + drawResistance = true; + drawIResistance = true; + + // + manageLegs = true; + manageZones = true; + manageIZones = true; + manageTrends = false; + manageOrderFlow = true; + + // + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Manage ... + Manage(iBar); + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + + // + // Remove TP if in Profit SL ... + iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + has = + (positions[i].IsBullish() && HasResistance()) + ? (iGuard.sl >= iValue && + positions[i].tp < resistance.lower) + : (positions[i].IsBearish() && HasSupport()) + ? (iGuard.sl <= iValue && + positions[i].tp > support.upper) + : false; + if (has) + { + // + iGuard.Clean(); + iGuard.force = false; + iGuard.tp = positions[i].IsBullish() + ? resistance.lower + : support.upper; + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + } + } + } + } + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + void Manage(XOHCL &bar) + { + // + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + has = bar.GetPreviousBar(pBar); + has = has && + pBar.GetPreviousBar(p2Bar); + has = has && + p2Bar.GetPreviousBar(p3Bar); + if (!has) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + ManageLeg(bar); + ManageTrends(bar); + ManageZones(p2Bar); + ManageIZones(p2Bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + // Private ... + private: + // + // Props ... + + // + // Leg ... + + XLeg leg; // Exists Leg ... + bool drawLeg; // Draw Leg ... + bool manageLegs; + + // + bool HasLeg() + { + return leg.IsValid(); + } + + // + bool ValidateLeg(XOHCL &bar) + { + // + bool result = false; + + // + result = HasLeg() && + bar.IsValid(); + if (!result) + { + return result; + } + + // + result = + leg.IsBullish() + ? bar.low > leg.lower + : leg.IsBearish() + ? bar.high < leg.upper + : false; + + // + return result; + } + + // + void DrawLeg() + { + // + if (!drawLeg) + { + return; + } + + // + if (!HasLeg()) + { + return; + } + + // + // Update to Times ... + leg.UpdateTimes(); + + // + // Draw Leg Box ... + XBoxZone legZone; + leg.ToBox(legZone); + if (legZone.IsValid()) + { + // + legZone.to = TimeCurrent(); + poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig); + } + + // + // Draw Legs Other Stufs ... + return; + + // + // FVGs ... + poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig); + + // + // Support and Resistances ... + poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig); + + // + // Patterns ... + poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig); + } + + // + void ManageLeg(XOHCL &bar) + { + // + // Validate Exists ... + if (HasLeg()) + { + // + if (!ValidateLeg(bar)) + { + // + // Invalidate XLeg ... + leg.Clean(); + } + } + + // + // Detect New ... + if (!HasLeg()) + { + poiDetector.IsLegPattern(bar, leg); + } + + // + // Update Exists ... + if (HasLeg()) + { + // + // Update to Times ... + leg.UpdateTimes(); + + // + DrawLeg(); + } + } + + // + // Order Flow ... + + // + bool drawOrderFlow; + XBoxZone orderFlow[]; + bool manageOrderFlow; + ENUM_X_DIRECTION orderFlowDir; + + // + bool HasOrderFlow() + { + // + return HasChild(orderFlow) && + HasDirection(orderFlowDir); + } + + // + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + // + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + + // + bool GetOrderFlowBoundary( + double &upper, + double &lower // + ) + { + // + bool result = false; + + // + // Prepare ... + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + + // + // Validate ... + result = HasOrderFlow(); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Upper ... + idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + upper = orderFlow[idx].upper; + } + + // + // Lower ... + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + lower = orderFlow[idx].lower; + } + + // + result = NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + // Cleanup ... + if (!result) + { + // + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + } + + // + return result; + } + + // + bool ValidateOrderFlow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasOrderFlow(); + if (!result) + { + return result; + } + + // + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + result = GetOrderFlowBoundary(upper, lower); + result = result && + HasBullishOrderFlow() + ? bar.low > lower + : bar.high < upper; + + // + return result; + } + + // + void DrawOrderFlow() + { + // + if (!drawOrderFlow || !HasOrderFlow()) + { + return; + } + + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); + } + + // + void ManageOrderFlow(XOHCL &bar) + { + // + // Validate Exists ... + if (HasOrderFlow()) + { + // + if (!ValidateOrderFlow(bar)) + { + // + // Invalidate OrderFlow ... + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + } + + // + // Detect New ... + if (!HasOrderFlow()) + { + // + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // patternConfig.Default(); + // patternConfig.supportAndResistanceLoopbackLength = 21; + // patternConfig.supportAndResistanceValidationLength = 7; + + // + poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + } + + // + // Update Exists ... + if (HasOrderFlow()) + { + // + // Update to Times ... + UpdateToTime(orderFlow, TimeCurrent()); + + // + DrawOrderFlow(); + } + } + + // + // Zone ... + + // + XBoxZone support; + XBoxZone resistance; + bool drawZones; + bool drawSupport; + bool manageZones; + bool drawResistance; + + // + bool HasZones() + { + return HasSupport() || + HasResistance(); + } + + // + bool HasSupport() + { + return support.IsValid(); + } + + // + bool HasResistance() + { + return resistance.IsValid(); + } + + // + bool ValidateZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; + } + + // + void DrawZones() + { + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } + } + + // + void ManageZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + // + if (support.IsValid()) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + // + if (resistance.IsValid()) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASup"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + XBoxZone iSupport; + XBoxZone iResistance; + bool drawIZones; + bool drawISupport; + bool manageIZones; + bool drawIResistance; + + // + bool HasIZones() + { + // + return HasISupport() || + HasIResistance(); + } + + // + bool HasISupport() + { + return iSupport.IsValid(); + } + + // + bool HasIResistance() + { + return iResistance.IsValid(); + } + + // + void DrawIZones() + { + // + if (!drawIZones || !HasIZones()) + { + return; + } + + // + if (drawISupport && HasISupport()) + { + poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig); + } + + // + if (drawIResistance && HasIResistance()) + { + poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig); + } + } + + // + bool ValidateIZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasIZones(); + if (!result) + { + return result; + } + + // + + // + // Support ... + bool hasSupport = HasISupport(); + if (hasSupport) + { + // + result = bar.close > iSupport.lower && + !IsBreaked(iSupport, X_PRICE_CLOSE); + if (!result) + { + // + iSupport.breakAt = bar.time; + iSupport.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasIResistance(); + if (hasResistance) + { + // + result = bar.close < iResistance.upper && + !IsBreaked(iResistance, X_PRICE_CLOSE); + if (!result) + { + // + iResistance.breakAt = bar.time; + iResistance.Clean(); + } + } + + // + result = + (hasSupport && !HasISupport()) || + (hasResistance && !HasIResistance()); + + // + return result; + } + + // + void ManageIZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasIZones()) + { + // + if (!ValidateIZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(iSupport.breakAt)) + { + iSupport.Clean(); + } + + // + // Resistance ... + if (IsXValid(iResistance.breakAt)) + { + iResistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasIZones()) + { + // + if (HasISupport()) + { + // + iSupport.to = bar.time; + iSupport.type = "XFIMAISup"; + } + + // + if (HasIResistance()) + { + // + iResistance.to = bar.time; + iResistance.type = "XFIMAIRes"; + } + + // + DrawIZones(); + } + } + + // + // Trends ... + + // + XTrend scTrend; + XTrend mcTrend; + XTrend lcTrend; + XTrend hcTrend; + + // + bool drawTrends; + bool drawSCTrend; + bool drawMCTrend; + bool drawLCTrend; + bool drawHCTrend; + bool manageTrends; + + // + bool HasTrend() + { + // + bool result = + HasSCTrend() || + HasMCTrend() || + HasLCTrend() || + HasHCTrend(); + + // + return result; + } + + // + bool HasSCTrend() + { + return scTrend.IsValid() && + scTrend.HasTrend(); + } + + // + bool HasMCTrend() + { + return mcTrend.IsValid() && + mcTrend.HasTrend(); + } + + // + bool HasLCTrend() + { + return lcTrend.IsValid() && + lcTrend.HasTrend(); + } + + // + bool HasHCTrend() + { + return hcTrend.IsValid() && + hcTrend.HasTrend(); + } + + // + void DrawTrends() + { + // + if (!drawTrends || !HasTrend()) + { + return; + } + + // + // SC ... + if (drawSCTrend && HasSCTrend()) + { + poiDrawer.DrawTrendLine(scTrend, structureDrawConfig.drawConfig); + } + + // + // MC ... + if (drawMCTrend && HasMCTrend()) + { + poiDrawer.DrawTrendLine(mcTrend, structureDrawConfig.drawConfig); + } + + // + // LC ... + if (drawLCTrend && HasLCTrend()) + { + poiDrawer.DrawTrendLine(lcTrend, structureDrawConfig.drawConfig); + } + + // + // HC ... + if (drawHCTrend && HasHCTrend()) + { + poiDrawer.DrawTrendLine(hcTrend, structureDrawConfig.drawConfig); + } + } + + // + void ManageTrends(XOHCL &bar) + { + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XTrend tmpTrend; + + // + // SC ... + tmpTrend.Clean(); + has = fimaParser.HasSCTrend(tmpTrend, bar.Index()); + if (has) + { + scTrend = tmpTrend; + } + + // + // MC ... + tmpTrend.Clean(); + has = fimaParser.HasMCTrend(tmpTrend, bar.Index()); + if (has) + { + mcTrend = tmpTrend; + } + + // + // LC ... + tmpTrend.Clean(); + has = fimaParser.HasLCTrend(tmpTrend, bar.Index()); + if (has) + { + lcTrend = tmpTrend; + } + + // + // HC ... + tmpTrend.Clean(); + has = fimaParser.HasHCTrend(tmpTrend, bar.Index()); + if (has) + { + hcTrend = tmpTrend; + } + + // + DrawTrends(); + + // + // Cleanup ... + tmpTrend.Clean(); + } + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = false; + bool useSignaller2 = true; + bool useSignaller3 = true; + bool useSignaller4 = true; + + // + // Validator Flags ... + string provider = NULL; + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = false; + bool drawMarketStructureAnalysis = false; + bool drawMarketStructureOrderFlow = false; + XPOIDrawConfig iDrawConfig; + + // + drawLeg = false; + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Signaller 1 ... + if (!result && useSignaller1) + { + // + result = Strategy1HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "1"; + } + } + + // + // Signaller 2 ... + if (!result && useSignaller2) + { + // + result = Strategy2HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "2"; + } + } + + // + // Signaller 3 ... + if (!result && useSignaller3) + { + // + result = Strategy3HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "3"; + } + } + + // + // Signaller 4 ... + if (!result && useSignaller4) + { + // + result = Strategy4HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "4"; + } + } + + // + // Signal Validating ... + + // + // Validate Signals by Order Flow ... + if (result && validateByOrderFlow) + { + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + + // + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Prepare Draw Config ... + iDrawConfig = structureDrawConfig.drawConfig; + iDrawConfig.zonesWidth = 3; + iDrawConfig.zonesStyle = STYLE_DASH; + iDrawConfig.bullishColor = clrYellow; + iDrawConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (drawZone) + { + poiDrawer.DrawZone(zone, iDrawConfig); + } + + // + // Draw Market Structure ... + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } + } + + // + // Other Drawing Materials ... + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Reading Conditions ... + int pullBackStartBar = -1; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + zone, + dir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(dir); + bool isPullbackBearish = isPullBack && + IsXBearish(dir); + if (isPullBack) + { + pullBackStartBar = zone.FromIndex(); + } + + // + // Reading HK Band ... + + // + double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index()); + double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index()); + int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH); + + // + // Reading PV Requirements ... + + // + int lastPeakOverLastIDX = -1; + int lastValeUnderLastIDX = -1; + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + int samePeaks = fimaParser.CountSamePeaks(pBar.Index()); + int sameVales = fimaParser.CountSameVales(pBar.Index()); + fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + + // + // Try To Find Affected Zone ... + + // + // Collecting Zones ... + XBoxZone zones[]; + XBoxZone affectedZones[]; + XBoxZone affectedZonesBullish[]; + XBoxZone affectedZonesBearish[]; + int zonesCount = poiDetector.CollectZones( + pBar, + zones, // + 5, // Zones Loopback ... + 3 // Zones Validation Length ... + // Required Zones ... + // Loopback ... + ); + int affectedZonesCount = ExtractAffectedZones( + pBar, + zones, + affectedZones // + ); + int affectedZonesBullishCount = ExtractByDirection( + affectedZonesBullish, + affectedZones, + X_DIRECTION_BULLISH // + ); + int affectedZonesBearishCount = ExtractByDirection( + affectedZonesBearish, + affectedZones, + X_DIRECTION_BEARISH // + ); + + // + int insideBullishIDX = -1; + int insideBearishIDX = -1; + bool hasBullishInside = + pBar.IsBullish() && + HasInside( + insideBullishIDX, + pBar, + affectedZonesBullish // + ); + bool hasBearishInside = + pBar.IsBearish() && + HasInside( + insideBearishIDX, + pBar, + affectedZonesBearish // + ); + + // + // Do ... + + // + isBullish = + // + hasBullishInside && + isPullbackBullish && + isPBarHasBullishPatterns && + fimaParser.IsSARBullish(pBar.Index()) && + (pVale >= affectedZonesBullish[insideBullishIDX].lower && + pVale <= affectedZonesBullish[insideBullishIDX].upper) + // + ; + + // + isBearish = + // + hasBearishInside && + isPullbackBearish && + isPBarHasBearishPatterns && + fimaParser.IsSARBearish(pBar.Index()) && + (pPeak >= affectedZonesBearish[insideBearishIDX].lower && + pPeak <= affectedZonesBearish[insideBearishIDX].upper) + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + if (isBullish) + { + zone = affectedZonesBullish[insideBullishIDX]; + } + else + { + zone = affectedZonesBearish[insideBearishIDX]; + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + XClean(zones); + pBarAnalysis.Clean(); + XClean(affectedZones); + XClean(affectedZonesBullish); + XClean(affectedZonesBearish); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Do ... + + // + isBullish = + // + isFastOverLast && + isValeUnderLast && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + isPeakOverLast && + isFastUnderLast && + !isP2ValeOverLast && + isPBarCloseUnderFast && + isP2BarBearishPinned && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Manage Stops ... + if (result) + { + // + double entry = GetEntry(zone.symbol, zone.dir); + double riskSide = zone.IsBullish() ? zone.lower : zone.upper; + double risk = MathAbs(entry - riskSide); + + // + // Collecting Affected Zones ... + XBoxZone tmps[]; + XBoxZone zones[]; + XBoxZone actedZones[]; + XBoxZone insideZones[]; + XBoxZone breakedZones[]; + XBoxZone affectedZones[]; + + // + // Support and Resistances ... + poiDetector.CollectZones(bar, tmps); + Copy(tmps, zones, false); + + // + // OBS ... + poiDetector.CollectOBs(bar, tmps); + Copy(tmps, zones, false); + + // + // FVGs ... + poiDetector.CollectFVGs(bar, tmps); + Copy(tmps, zones, false); + + // + ExtractAffectedZones(bar, zones, affectedZones); + + // + // Acteds Zones ... + ExtractActeds(bar, actedZones, affectedZones); + + // + // Inside Zones ... + ExtractInsides(bar, insideZones, affectedZones); + + // + // Breaked Zones ... + ExtractBreakeds(bar, breakedZones, affectedZones); + + // + // Cleanup ... + XClean(tmps); + XClean(zones); + XClean(actedZones); + XClean(insideZones); + XClean(breakedZones); + XClean(affectedZones); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Strategy 3: + * =========== + * - Works Based On Breaked Support or Resistances ... + * - Looking for a Support or Resistance to Breaked ... + * - Validate Breaker Bar to Change Peak or Vale ... + * - Validate Bar Opposit Side of Breaker Bar's Shadow ... + * - Validate by Checking Market Strucutre to Has Directional Zone + * (Support for Resistance Break / Resistance for Support Break) ... + * - Validate Breaker Bar to Has Directional FVG ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + + // + bool validateByPVChanges = true; + bool validateByGapExists = true; + bool validateByBarShadows = true; + bool validateHasDirectionalZone = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XBoxZone _fvg; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + // Price Must Break Support or Resistance ... + + // + // Extract Support and Resistance ... + bool hasSupport = p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsResistance(); + if (hasSupport) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, _support); + tmpBar.Clean(); + tmpPivot.Clean(); + } + if (hasResistance) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + tmpBar.Clean(); + tmpPivot.Clean(); + } + + // + bool hasBreakedSupport = hasSupport && + pBar.close < _support.lower && + p2Bar.close > _support.lower; + bool hasBreakedResistance = hasResistance && + pBar.close > _resistance.upper && + p2Bar.close < _resistance.upper; + + // + isBullish = hasBreakedResistance; + isBearish = hasBreakedSupport; + + // + result = isBullish || isBearish; + + // + // Validate By PV Changed ... + // Breaker Bar must Change Peak or Value ... + if (result && validateByPVChanges) + { + // + bool isPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + + // + isBullish = + isBullish && + isPeakOverLast; + + // + isBearish = + isBearish && + isValeUnderLast; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Bar Shadows ... + // Breakre Bar Side Shadow must not Reached ... + if (result && validateByBarShadows) + { + // + isBullish = + isBullish && + pBar.low > p2Bar.low; + + // + isBearish = + isBearish && + pBar.high < p2Bar.high; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Has Directional Zone ... + if (result && validateHasDirectionalZone) + { + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate By Gap Exists ... + if (result && validateByGapExists) + { + // + ENUM_X_DIRECTION tmpDir; + bool hasFVG = poiDetector.HasFVG( + pBar, + tmpDir, + _fvg // + ); + + // + isBullish = + isBullish && + hasFVG && + IsXBullish(tmpDir); + + // + isBearish = + isBearish && + hasFVG && + IsXBearish(tmpDir); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Prepare Direction and Zone ... + if (result) + { + // + if (isBullish) + { + // + zone = _resistance; + zone.dir = Opposit(_resistance.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + if (isBearish) + { + // + zone = _support; + zone.dir = Opposit(_support.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + // Zone Validation Base ... + result = zone.IsValid(); + if (result) + { + // + // Validate By Trend of Zone ... + XTrend zoneTrend; + XTrend zoneToTrend; + + // + // Detecting Trends ... + result = poiDetector.HasBoundaryTrend(zone, zoneTrend, false); + result = result && + poiDetector.HasBoundaryTrend(zone, zoneToTrend, true); + + // + // Validate Trend ... + result = + result && + zone.dir == zoneTrend.dir && + zone.dir == zoneToTrend.dir; + + // + // Draw ... + if (result) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + poiDrawer.DrawTrendLine(zoneTrend, iConfig); + poiDrawer.DrawTrendLine(zoneToTrend, iConfig); + + // + iConfig.Clean(); + } + + // + // Cleanup ... + zoneTrend.Clean(); + zoneToTrend.Clean(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + result = zone.IsValid(); + } + + // + if (result) + { + // + if (_support.IsValid()) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (_resistance.IsValid()) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (pBarPatterns.IsValid()) + { + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + patternConfig.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Strategy 4: + * =========== + * - Works Based on Order Flow ... + * - Looking for new and Fresh Order Flow ... + * - Validate Bar is Inside Order Flow ... + * - Validate Bar has Proper Pattern ... + * - Validate Bar Based on ATR Band in two Step: + * - Step 1: Bars is Inside ATR Band (Middle) ... + * - Step 2: Trigger Bars Close Price based on ATR Band ... + * - Validate Order Flow based on Market Structure Zone ... + * - Validate Trigger Bar based on InDirectional Market Structure Zones ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateBarInsideZone = true; + bool validateByBarPatterns = true; + bool validateByXFIMABoundary = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = true; + bool validateMarketStructureHasDirectionalZone = true; + bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; + bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + // Detecting OrderFlow ... + XBoxZone oFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + p3Bar, + dir, + oFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + + // + XTrend boundaryTrend; + XTrend boundaryZoneTrend; + + // + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + double atrBandMiddle = EMPTY_VALUE; + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force Price of p2Bar is Inside Order Flow ... + if (result && validateBarInsideZone) + { + // + double orderFlowUpper = 0; + double orderFlowLower = 0; + + // + int idx = -1; + idx = GetHighest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowUpper = oFlow[idx].upper; + } + idx = GetLowest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowLower = oFlow[idx].lower; + } + + // + result = NotEmptyZero(orderFlowUpper) && + NotEmptyZero(orderFlowLower) && + orderFlowUpper > orderFlowLower && + (isBullish + ? p2Bar.low < orderFlowUpper + : p2Bar.high > orderFlowLower); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + // (bar.close > pBar.low || + // bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + // (bar.close < pBar.high || + // bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force P2Bar Place Checking based on ATR Band ... + if (result && validateByBarInsideATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); + + // + atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); + + // + isBullish = + isBullish && + NotEmptyZero(atrBandMiddle) && + p2Bar.low < atrBandMiddle; + + // + isBearish = + isBearish && + NotEmptyZero(atrBandMiddle) && + p2Bar.high > atrBandMiddle; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Place Checking based on ATR Band ... + if (result && validateByBarBasedOnATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); + + // + result = + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower) && + (isBullish + ? pBar.close > atrBandLower + : pBar.close < atrBandUpper); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // for Bullish has Support ... + // for Bearish has Resistance ... + if (result && validateMarketStructureHasDirectionalZone) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Validate Support and Resistance by Order Flow ... + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + // Check Market Strucutre Support and Resistance Validation ... + if (validateMarketStructureDirectionalZoneInsideOrderFlow) + { + // + hasSupport = + hasOFBox && + hasSupport && + ofZone.lower < _support.lower && + ofZone.upper > _support.upper; + + // + hasResistance = + hasOFBox && + hasResistance && + ofZone.lower < _resistance.lower && + ofZone.upper > _resistance.upper; + } + + // + // Validate Directional Support or Resistance Exists ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Makret Structure Has Not Indirectional Zone ... + if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + bool hasIndirectionalZone = + (isBullish && hasResistance) || + (isBearish && hasSupport); + if (hasIndirectionalZone) + { + // + // Here we Have to Validate Zone Place ... + + // + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Bullish ... + if (isBullish && hasResistance) + { + hasResistance = _resistance.lower <= tp; + } + + // + // Bearish ... + if (isBearish && hasSupport) + { + hasSupport = _support.upper >= tp; + } + } + + // + isBullish = + isBullish && + !hasResistance; + + // + isBearish = + isBearish && + !hasSupport; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate ... + result = isBullish || isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone and do Zone Based Validations ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Refine Zone ... + zone.to = bar.time; + zone.upper = MathMax(zone.upper, atrBandMiddle); + zone.lower = MathMin(zone.lower, atrBandMiddle); + + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Try to Retrieve Boundary To Trend ... + result = poiDetector.HasBoundaryTrend( + zone, + boundaryTrend, + true // + ); + + // + // Try to Retrieve Boundary Zone Trend ... + result = + result && + poiDetector.HasBoundaryTrend( + zone, + boundaryZoneTrend, + false // + ); + + // + // Check and Validate Trend Direction ... + result = + result && + zone.dir == boundaryTrend.dir && + zone.dir == boundaryZoneTrend.dir; + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + } + } + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + XTarget iTarget; + + // + // Calculate Requirements ... + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // High Risk Target is Used to Protect In Profit Positiions + // from Reversal Patterns ... + double highRiskR2r = (defaultSignalR2R / 5) * 4; + double highRiskReward = highRiskR2r * risk; + double highRiskTP = isBullish + ? entry + highRiskReward + : entry - highRiskReward; + iTarget.Clean(); + iTarget.actingDistance = 5; + iTarget.doRFOnEntry = true; + iTarget.target = highRiskTP; + iTarget.volumeMultiplier = 0.8; + // AddRef(iTarget, targets); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(oFlow); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); + boundaryZoneTrend.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class.mq5 b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class.mq5 new file mode 100644 index 0000000..5d1c13b --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class.mq5 @@ -0,0 +1,2621 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure ... + drawLeg = true; + drawOrderFlow = true; + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Manage ... + Manage(iBar); + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + + // + // Force Hedging ... + // bool forceHedging = (positionsCount >= 2); + // if (forceHedging) + // { + // // + // // Minimum Required Reward ... + // double minRequiredReward = 1.5; + + // // + // // Summarizing Risk and Reward of Collections ... + // // double risk = 0; + // // double volume = 0; + // // double reward = 0; + // // for (int i = 0; i < positionsCount; i++) + // // { + // // // + // // risk += positions[i].GetRisk() + positions[i].commission + (-1 * positions[i].swap); + // // reward += positions[i].profit; + // // volume += positions[i].volume; + // // } + + // // // + // // risk *= volume; + // // reward *= volume; + + // // // + // // // Calculating Can Hedge rops ... + // // has = reward >= (risk * minRequiredReward); + // // if (has) + // // { + // // // + // // iGuard.Clean(); + // // iGuard.force = true; + // // iGuard.symbol = symbol; + // // iGuard.period = period; + // // iGuard.provider = name; + // // iGuard.time = TimeCurrent(); + // // iGuard.action = X_GUARD_ACTION_HEDGE; + + // // // + // // // Validate Guard ... + // // has = iGuard.IsValid(); + // // if (has) + // // { + // // // + // // AddRef( + // // iGuard, + // // guards // + // // ); + // // } + // // } + // } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + void Manage(XOHCL &bar) + { + // + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + has = bar.GetPreviousBar(pBar); + has = has && + pBar.GetPreviousBar(p2Bar); + has = has && + p2Bar.GetPreviousBar(p3Bar); + if (!has) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + ManageLeg(bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + // Private ... + private: + // + // Props ... + + // + // Leg ... + + XLeg leg; // Exists Leg ... + bool drawLeg; // Draw Leg ... + + // + bool HasLeg() + { + return leg.IsValid(); + } + + // + bool ValidateLeg(XOHCL &bar) + { + // + bool result = false; + + // + result = HasLeg() && + bar.IsValid(); + if (!result) + { + return result; + } + + // + result = + leg.IsBullish() + ? bar.low > leg.lower + : leg.IsBearish() + ? bar.high < leg.upper + : false; + + // + return result; + } + + // + void DrawLeg() + { + // + if (!drawLeg) + { + return; + } + + // + if (!HasLeg()) + { + return; + } + + // + // Update to Times ... + leg.UpdateTimes(); + + // + // Draw Leg Box ... + XBoxZone legZone; + leg.ToBox(legZone); + if (legZone.IsValid()) + { + // + legZone.to = TimeCurrent(); + poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig); + } + + // + // Draw Legs Other Stufs ... + return; + + // + // FVGs ... + poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig); + + // + // Support and Resistances ... + poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig); + + // + // Patterns ... + poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig); + } + + // + void ManageLeg(XOHCL &bar) + { + // + // Validate Exists ... + if (HasLeg()) + { + // + if (!ValidateLeg(bar)) + { + // + // Invalidate XLeg ... + leg.Clean(); + } + } + + // + // Detect New ... + if (!HasLeg()) + { + poiDetector.IsLegPattern(bar, leg); + } + + // + // Update Exists ... + if (HasLeg()) + { + // + // Update to Times ... + leg.UpdateTimes(); + + // + DrawLeg(); + } + } + + // + // Order Flow ... + + // + bool drawOrderFlow; + XBoxZone orderFlow[]; + ENUM_X_DIRECTION orderFlowDir; + + // + bool HasOrderFlow() + { + // + return HasChild(orderFlow) && + HasDirection(orderFlowDir); + } + + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + + bool GetOrderFlowBoundary( + double &upper, + double &lower // + ) + { + // + bool result = false; + + // + // Prepare ... + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + + // + // Validate ... + result = HasOrderFlow(); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Upper ... + idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + upper = orderFlow[idx].upper; + } + + // + // Lower ... + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + lower = orderFlow[idx].lower; + } + + // + result = NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + // Cleanup ... + if (!result) + { + // + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + } + + // + return result; + } + + bool ValidateOrderFlow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasOrderFlow(); + if (!result) + { + return result; + } + + // + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + result = GetOrderFlowBoundary(upper, lower); + result = result && + HasBullishOrderFlow() + ? bar.low > lower + : bar.high < upper; + + // + return result; + } + + void DrawOrderFlow() + { + // + if (!drawOrderFlow || !HasOrderFlow()) + { + return; + } + + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); + } + + void ManageOrderFlow(XOHCL &bar) + { + // + // Validate Exists ... + if (HasOrderFlow()) + { + // + if (!ValidateOrderFlow(bar)) + { + // + // Invalidate OrderFlow ... + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + } + + // + // Detect New ... + if (!HasOrderFlow()) + { + // + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // patternConfig.Default(); + // patternConfig.supportAndResistanceLoopbackLength = 21; + // patternConfig.supportAndResistanceValidationLength = 7; + + // + poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + } + + // + // Update Exists ... + if (HasOrderFlow()) + { + // + // Update to Times ... + UpdateToTime(orderFlow, TimeCurrent()); + + // + DrawOrderFlow(); + } + } + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = false; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = true; + + // + // Validator Flags ... + string provider = NULL; + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = true; + bool drawMarketStructureAnalysis = true; + bool drawMarketStructureOrderFlow = true; + XPOIDrawConfig iDrawConfig; + + // + drawLeg = false; + drawOrderFlow = false; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Check Market ... + // result = HasLeg() && + // HasOrderFlow() && + // orderFlowDir == leg.dir; + // result = HasBearishOrderFlow(); + // if (result) + // { + // // + // result = false; + // DebugBreak(); + // } + + // + // Signaller 1 ... + if (!result && useSignaller1) + { + // + result = Strategy1HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "1"; + } + } + + // + // Signaller 2 ... + if (!result && useSignaller2) + { + // + result = Strategy2HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "2"; + } + } + + // + // Signaller 3 ... + if (!result && useSignaller3) + { + // + result = Strategy3HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "3"; + } + } + + // + // Signaller 4 ... + if (!result && useSignaller4) + { + // + result = Strategy4HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "4"; + } + } + + // + // Signal Validating ... + + // + // Validate Signals by Order Flow ... + if (result && validateByOrderFlow) + { + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + + // + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Prepare Draw Config ... + iDrawConfig = structureDrawConfig.drawConfig; + iDrawConfig.zonesWidth = 3; + iDrawConfig.zonesStyle = STYLE_DASH; + iDrawConfig.bullishColor = clrYellow; + iDrawConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (drawZone) + { + poiDrawer.DrawZone(zone, iDrawConfig); + } + + // + // Draw Market Structure ... + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } + } + + // + // Other Drawing Materials ... + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Debug Breake ... + if (result) + { + DebugBreak(); + } + + // + // Cleanup ... + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Reading Conditions ... + int pullBackStartBar = -1; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + zone, + dir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(dir); + bool isPullbackBearish = isPullBack && + IsXBearish(dir); + if (isPullBack) + { + pullBackStartBar = zone.FromIndex(); + } + + // + // Reading HK Band ... + + // + double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index()); + double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index()); + int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH); + + // + // Reading PV Requirements ... + + // + int lastPeakOverLastIDX = -1; + int lastValeUnderLastIDX = -1; + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + int samePeaks = fimaParser.CountSamePeaks(pBar.Index()); + int sameVales = fimaParser.CountSameVales(pBar.Index()); + fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + + // + // Try To Find Affected Zone ... + + // + // Collecting Zones ... + XBoxZone zones[]; + XBoxZone affectedZones[]; + XBoxZone affectedZonesBullish[]; + XBoxZone affectedZonesBearish[]; + int zonesCount = poiDetector.CollectZones( + pBar, + zones, // + 5, // Zones Loopback ... + 3 // Zones Validation Length ... + // Required Zones ... + // Loopback ... + ); + int affectedZonesCount = ExtractAffectedZones( + pBar, + zones, + affectedZones // + ); + int affectedZonesBullishCount = ExtractByDirection( + affectedZonesBullish, + affectedZones, + X_DIRECTION_BULLISH // + ); + int affectedZonesBearishCount = ExtractByDirection( + affectedZonesBearish, + affectedZones, + X_DIRECTION_BEARISH // + ); + + // + int insideBullishIDX = -1; + int insideBearishIDX = -1; + bool hasBullishInside = + pBar.IsBullish() && + HasInside( + insideBullishIDX, + pBar, + affectedZonesBullish // + ); + bool hasBearishInside = + pBar.IsBearish() && + HasInside( + insideBearishIDX, + pBar, + affectedZonesBearish // + ); + + // + // Do ... + + // + isBullish = + // + hasBullishInside && + isPullbackBullish && + isPBarHasBullishPatterns && + fimaParser.IsSARBullish(pBar.Index()) && + (pVale >= affectedZonesBullish[insideBullishIDX].lower && + pVale <= affectedZonesBullish[insideBullishIDX].upper) + // + ; + + // + isBearish = + // + hasBearishInside && + isPullbackBearish && + isPBarHasBearishPatterns && + fimaParser.IsSARBearish(pBar.Index()) && + (pPeak >= affectedZonesBearish[insideBearishIDX].lower && + pPeak <= affectedZonesBearish[insideBearishIDX].upper) + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + if (isBullish) + { + zone = affectedZonesBullish[insideBullishIDX]; + } + else + { + zone = affectedZonesBearish[insideBearishIDX]; + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + XClean(zones); + pBarAnalysis.Clean(); + XClean(affectedZones); + XClean(affectedZonesBullish); + XClean(affectedZonesBearish); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Do ... + + // + isBullish = + // + isFastOverLast && + isValeUnderLast && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + isPeakOverLast && + isFastUnderLast && + !isP2ValeOverLast && + isPBarCloseUnderFast && + isP2BarBearishPinned && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Manage Stops ... + if (result) + { + // + double entry = GetEntry(zone.symbol, zone.dir); + double riskSide = zone.IsBullish() ? zone.lower : zone.upper; + double risk = MathAbs(entry - riskSide); + + // + // Collecting Affected Zones ... + XBoxZone tmps[]; + XBoxZone zones[]; + XBoxZone actedZones[]; + XBoxZone insideZones[]; + XBoxZone breakedZones[]; + XBoxZone affectedZones[]; + + // + // Support and Resistances ... + poiDetector.CollectZones(bar, tmps); + Copy(tmps, zones, false); + + // + // OBS ... + poiDetector.CollectOBs(bar, tmps); + Copy(tmps, zones, false); + + // + // FVGs ... + poiDetector.CollectFVGs(bar, tmps); + Copy(tmps, zones, false); + + // + ExtractAffectedZones(bar, zones, affectedZones); + + // + // Acteds Zones ... + ExtractActeds(bar, actedZones, affectedZones); + + // + // Inside Zones ... + ExtractInsides(bar, insideZones, affectedZones); + + // + // Breaked Zones ... + ExtractBreakeds(bar, breakedZones, affectedZones); + + // + // Cleanup ... + XClean(tmps); + XClean(zones); + XClean(actedZones); + XClean(insideZones); + XClean(breakedZones); + XClean(affectedZones); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Do ... + // XFIMA Consolidation ... + + // + bool isConsolidation = poiDetector.DetectPVConsolidationZone( + zone, + pBar.Index(), + true, // Force PV Break ... + true // Force Has Sar Switch ... + ); + + // + isBullish = + isConsolidation && + zone.IsBullish(); + + // + isBearish = + isConsolidation && + zone.IsBearish(); + + // + // Validate based on Bars Patterns ... + bool validateByBarPatterns = true; + if (validateByBarPatterns) + { + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || + isBearish; + } + + // + // Checking PullBack ... + bool validateByPullback = false; + if (validateByPullback) + { + // + XBoxZone pullback; + ENUM_X_DIRECTION pullbackDir; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + pullback, + pullbackDir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(pullbackDir); + bool isPullbackBearish = isPullBack && + IsXBearish(pullbackDir); + + // + isBullish = + isBullish && + isPullbackBullish; + + // + isBearish = + isBearish && + isPullbackBearish; + + // + // Summarize Result ... + result = isBullish || + isBearish; + } + + // + // Validate ... + result = isBullish || + isBearish; + + // + // Prepare Zone ... + if (result) + { + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Strategy 4: + * =========== + * - Works Based on Order Flow ... + * - Looking for new and Fresh Order Flow ... + * - Validate Bar is Inside Order Flow ... + * - Validate Bar has Proper Pattern ... + * - Validate Bar Based on ATR Band in two Step: + * - Step 1: Bars is Inside ATR Band (Middle) ... + * - Step 2: Trigger Bars Close Price based on ATR Band ... + * - Validate Order Flow based on Market Structure Zone ... + * - Validate Trigger Bar based on InDirectional Market Structure Zones ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateBarInsideZone = true; + bool validateByBarPatterns = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateMarketStructureHasDirectionalZone = true; + bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; + bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + // Detecting OrderFlow ... + XBoxZone oFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + p3Bar, + dir, + oFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + + // + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + double atrBandMiddle = EMPTY_VALUE; + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force Price of p2Bar is Inside Order Flow ... + if (result && validateBarInsideZone) + { + // + double orderFlowUpper = 0; + double orderFlowLower = 0; + + // + int idx = -1; + idx = GetHighest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowUpper = oFlow[idx].upper; + } + idx = GetLowest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowLower = oFlow[idx].lower; + } + + // + result = NotEmptyZero(orderFlowUpper) && + NotEmptyZero(orderFlowLower) && + orderFlowUpper > orderFlowLower && + (isBullish + ? p2Bar.low < orderFlowUpper + : p2Bar.high > orderFlowLower); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + // (bar.close > pBar.low || + // bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + // (bar.close < pBar.high || + // bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force P2Bar Place Checking based on ATR Band ... + if (result && validateByBarInsideATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); + + // + atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); + + // + isBullish = + isBullish && + NotEmptyZero(atrBandMiddle) && + p2Bar.low < atrBandMiddle; + + // + isBearish = + isBearish && + NotEmptyZero(atrBandMiddle) && + p2Bar.high > atrBandMiddle; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Place Checking based on ATR Band ... + if (result && validateByBarBasedOnATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); + + // + result = + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower) && + (isBullish + ? pBar.close > atrBandLower + : pBar.close < atrBandUpper); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // for Bullish has Support ... + // for Bearish has Resistance ... + if (result && validateMarketStructureHasDirectionalZone) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone support; + XBoxZone resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, resistance); + } + + // + // Validate Support and Resistance by Order Flow ... + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + // Check Market Strucutre Support and Resistance Validation ... + if (validateMarketStructureDirectionalZoneInsideOrderFlow) + { + // + hasSupport = + hasOFBox && + hasSupport && + ofZone.lower < support.lower && + ofZone.upper > support.upper; + + // + hasResistance = + hasOFBox && + hasResistance && + ofZone.lower < resistance.lower && + ofZone.upper > resistance.upper; + } + + // + // Validate Directional Support or Resistance Exists ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + support.Clean(); + tmpPivot.Clean(); + resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Makret Structure Has Not Indirectional Zone ... + if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone support; + XBoxZone resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, resistance); + } + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + bool hasIndirectionalZone = + (isBullish && hasResistance) || + (isBearish && hasSupport); + if (hasIndirectionalZone) + { + // + // Here we Have to Validate Zone Place ... + + // + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Bullish ... + if (isBullish && hasResistance) + { + hasResistance = resistance.lower <= tp; + } + + // + // Bearish ... + if (isBearish && hasSupport) + { + hasSupport = support.upper >= tp; + } + } + + // + isBullish = + isBullish && + !hasResistance; + + // + isBearish = + isBearish && + !hasSupport; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + support.Clean(); + tmpPivot.Clean(); + resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Refine Zone ... + zone.to = bar.time; + zone.upper = MathMax(zone.upper, atrBandMiddle); + zone.lower = MathMin(zone.lower, atrBandMiddle); + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + + // + DebugBreak(); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + XTarget iTarget; + + // + // Calculate Requirements ... + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // High Risk Target is Used to Protect In Profit Positiions + // from Reversal Patterns ... + double highRiskR2r = (defaultSignalR2R / 5) * 4; + double highRiskReward = highRiskR2r * risk; + double highRiskTP = isBullish + ? entry + highRiskReward + : entry - highRiskReward; + iTarget.Clean(); + iTarget.actingDistance = 5; + iTarget.doRFOnEntry = true; + iTarget.target = highRiskTP; + iTarget.volumeMultiplier = 0.8; + AddRef(iTarget, targets); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(orderFlow); + pBarPatterns.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/XKI_MTF_EA.mq5 b/BKPS/14041018/Documents/BKP/XKI_MTF_EA.mq5 new file mode 100644 index 0000000..6fa8c1e --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XKI_MTF_EA.mq5 @@ -0,0 +1,547 @@ +//+------------------------------------------------------------------+ +//| XKI_MTF_EA.mq5 +//| SaherElm IT Center - Strategy using XKI +//| Author: Hadi Khazaee Asl +//+------------------------------------------------------------------+ +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// Inputs +input string InpSymbol = "XAUUSDb"; +input ENUM_TIMEFRAMES InpSignalTF = PERIOD_H1; // Signal timeframe (H1) +input int InpKiLength = 26; // KI length (XKI input) +input bool InpShowKI = true; // (XKI input) +input int InpCalcLastBars = 1500; // (XKI input) + +input bool InpUseRSI = true; // Use RSI confirmation +input int InpRSIPeriod = 14; +input int InpRSIPrice = PRICE_CLOSE; + +input bool InpUseH4Filter = true; // Confirm with H4 +input bool InpUseD1Filter = false; // Confirm with D1 +input bool InpRequireBothFilters = false; // If true, require BOTH H4 and D1 agreement; else either + +input double InpFixedLot = 0.10; // Fixed lot size +input double InpRiskATRMult = 0.0; // Add ATR padding to stop (0=disabled) +input int InpATRPeriod = 14; + +input double InpRR = 2.0; // Reward:Risk target +input bool InpTrailByKI = true; // Trail stop to KI +input int InpSlippagePoints = 20; // Max slippage in points +input int InpMaxSpreadPoints = 200; // Max allowed spread in points + +input bool InpAvoidAsianSession = true; // Avoid 22:00–06:00 server time +input int InpAsianStartHour = 22; +input int InpAsianEndHour = 6; + +input bool InpAvoidNewsWindow = false; // Placeholder flag +input int InpNewsWindowMinutes = 60; // Skip trades within +/- minutes + +input int InpBarsLookbackSignal = 2; // Lookback bars for signal (e.g., last closed bar) + +// Magic number and comments +input int InpMagic = 260126; +input string InpOrderComment = "XKI_MTF_EA"; + +// iCustom indicator path (relative to Indicators folder if compiled there) +string g_xkiIndicatorPath = "x-saherelm.x121.xki"; // the compiled name; adjust if different + +// Buffers indices as per the indicator +#define KI_BUFFER_INDEX 0 +#define KI_COLOR_IDX_BUFFER_INDEX 1 +#define KI_STATE_BUFFER_INDEX 2 + +// States from indicator +#define BULLISH_STATE 1 +#define NEUTURAL_STATE 0 +#define BEARISH_STATE -1 + +// Globals +int g_digits; +double g_point; +MqlTick g_tick; +int g_atrHandleH1 = INVALID_HANDLE; +int g_atrHandleH4 = INVALID_HANDLE; +int g_atrHandleD1 = INVALID_HANDLE; +int g_rsiHandleH1 = INVALID_HANDLE; +int g_rsiHandleH4 = INVALID_HANDLE; +int g_rsiHandleD1 = INVALID_HANDLE; + +//+------------------------------------------------------------------+ +// OnInit +//+------------------------------------------------------------------+ +int OnInit() +{ + // + g_digits = (int)SymbolInfoInteger(InpSymbol, SYMBOL_DIGITS); + g_point = SymbolInfoDouble(InpSymbol, SYMBOL_POINT); + + if (!SymbolInfoTick(InpSymbol, g_tick)) + { + Print("Failed to get tick for symbol: ", InpSymbol); + return INIT_FAILED; + } + + // Quick validation + if (InpKiLength < 5) + { + Print("Invalid KI length: ", InpKiLength); + return INIT_PARAMETERS_INCORRECT; + } + + // + GetOrCreateATRHandle(InpSymbol, InpSignalTF, InpATRPeriod); + if (InpUseH4Filter) + GetOrCreateATRHandle(InpSymbol, PERIOD_H4, InpATRPeriod); + if (InpUseD1Filter) + GetOrCreateATRHandle(InpSymbol, PERIOD_D1, InpATRPeriod); + + // + GetOrCreateRSIHandle(InpSymbol, InpSignalTF, InpRSIPeriod, InpRSIPrice); + if (InpUseH4Filter) + GetOrCreateRSIHandle(InpSymbol, PERIOD_H4, InpRSIPeriod, InpRSIPrice); + if (InpUseD1Filter) + GetOrCreateRSIHandle(InpSymbol, PERIOD_D1, InpRSIPeriod, InpRSIPrice); + + // + return INIT_SUCCEEDED; +} + +//+------------------------------------------------------------------+ +// OnDeinit +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + if (g_atrHandleH1 != INVALID_HANDLE) + { + IndicatorRelease(g_atrHandleH1); + g_atrHandleH1 = INVALID_HANDLE; + } + if (g_atrHandleH4 != INVALID_HANDLE) + { + IndicatorRelease(g_atrHandleH4); + g_atrHandleH4 = INVALID_HANDLE; + } + if (g_atrHandleD1 != INVALID_HANDLE) + { + IndicatorRelease(g_atrHandleD1); + g_atrHandleD1 = INVALID_HANDLE; + } + + // + if (g_rsiHandleH1 != INVALID_HANDLE) + { + IndicatorRelease(g_rsiHandleH1); + g_rsiHandleH1 = INVALID_HANDLE; + } + if (g_rsiHandleH4 != INVALID_HANDLE) + { + IndicatorRelease(g_rsiHandleH4); + g_rsiHandleH4 = INVALID_HANDLE; + } + if (g_rsiHandleD1 != INVALID_HANDLE) + { + IndicatorRelease(g_rsiHandleD1); + g_rsiHandleD1 = INVALID_HANDLE; + } +} + +//+------------------------------------------------------------------+ +// OnTick +//+------------------------------------------------------------------+ +void OnTick() +{ + if (_Symbol != InpSymbol) + return; + + // Basic trading safety + if (!SymbolInfoTick(InpSymbol, g_tick)) + return; + double spreadPoints = GetSpread(InpSymbol); + if (spreadPoints > InpMaxSpreadPoints) + return; + + if (InpAvoidAsianSession) + { + // + MqlDateTime now = GetCurrentTime(); + int hr = now.hour; + if (IsHourInRange(hr, InpAsianStartHour, InpAsianEndHour)) + return; + } + + if (InpAvoidNewsWindow) + { + // Placeholder: implement your own calendar integration + // Skip trading in a window near news. Here we simply return. + return; + } + + // Only process on new bar of signal timeframe + static datetime lastSignalBarTime = 0; + datetime currentSignalBarTime = GetLastClosedBarTime(InpSymbol, InpSignalTF); + if (currentSignalBarTime == 0 || currentSignalBarTime == lastSignalBarTime) + return; + lastSignalBarTime = currentSignalBarTime; + + // Get signal state and KI on signal TF (last closed bar) + int signalBarShift = InpBarsLookbackSignal; // 1=last closed, 2=previous + int stateSignal; + double kiSignal, closeSignal; + if (!GetXKIStateAndKI(InpSymbol, InpSignalTF, signalBarShift, stateSignal, kiSignal)) + return; + closeSignal = iClose(InpSymbol, InpSignalTF, signalBarShift); + + // RSI confirmation + if (InpUseRSI) + { + double rsi = GetRSIValue(InpSymbol, InpSignalTF, InpRSIPeriod, InpRSIPrice, signalBarShift); + if (rsi == EMPTY_VALUE) + return; + if (stateSignal == BULLISH_STATE && rsi <= 50.0) + return; + if (stateSignal == BEARISH_STATE && rsi >= 50.0) + return; + } + + // Higher timeframe agreement + bool agreesH4 = true, agreesD1 = true; + if (InpUseH4Filter) + agreesH4 = HigherTFAgrees(InpSymbol, PERIOD_H4, signalBarShift, stateSignal); + if (InpUseD1Filter) + agreesD1 = HigherTFAgrees(InpSymbol, PERIOD_D1, signalBarShift, stateSignal); + + bool filterOK = true; + if (InpUseH4Filter || InpUseD1Filter) + { + if (InpRequireBothFilters) + filterOK = (agreesH4 && agreesD1); + else + filterOK = ((InpUseH4Filter && agreesH4) || (InpUseD1Filter && agreesD1)); + } + if (!filterOK) + return; + + // Neutral or invalid skip + if (stateSignal == NEUTURAL_STATE) + return; + + // Ensure no open positions for this symbol/magic + if (HasOpenPosition(InpSymbol, InpMagic)) + return; + + // Prepare trade params + double atrPad = 0.0; + if (InpRiskATRMult > 0.0) + { + double atr = GetATRValue(InpSymbol, InpSignalTF, InpATRPeriod, signalBarShift); + if (atr != EMPTY_VALUE && atr > 0) + atrPad = atr * InpRiskATRMult; + } + + double sl, tp; + bool isBuy = (stateSignal == BULLISH_STATE); + if (isBuy) + { + sl = kiSignal - atrPad; + tp = closeSignal + (closeSignal - sl) * InpRR; + PlaceOrder(InpSymbol, ORDER_TYPE_BUY, InpFixedLot, sl, tp); + } + else if (stateSignal == BEARISH_STATE) + { + sl = kiSignal + atrPad; + tp = closeSignal - (sl - closeSignal) * InpRR; + PlaceOrder(InpSymbol, ORDER_TYPE_SELL, InpFixedLot, sl, tp); + } + + // After placement, trailing handled in OnTimer or OnTick below + if (InpTrailByKI) + TrailStopsByKI(); +} + +//+------------------------------------------------------------------+ +// Utilities +//+------------------------------------------------------------------+ +// +// Create or reuse an ATR handle for the given TF ... +int GetOrCreateATRHandle( + string symbol, + ENUM_TIMEFRAMES tf, + int period // +) +{ + int h = g_atrHandleH1; + if (tf == PERIOD_H4) + h = g_atrHandleH4; + else if (tf == PERIOD_D1) + h = g_atrHandleD1; + if (h == INVALID_HANDLE) + { + h = iATR(symbol, tf, period); + if (h == INVALID_HANDLE) + Print("Failed to create ATR handle: ", symbol, " ", EnumToString(tf), " period=", period); + } + return h; +} + +// +// Read ATR value for a specific bar shift (1=last closed bar) ... +double GetATRValue( + string symbol, + ENUM_TIMEFRAMES tf, + int period, + int shift // +) +{ + int h = GetOrCreateATRHandle(symbol, tf, period); + if (h == INVALID_HANDLE) + return EMPTY_VALUE; + + // + double buff[]; + + // + // Copy exactly one value at 'shift' ... + int copied = CopyBuffer(h, 0, shift, 1, buff); + if (copied != 1 || !MathIsValidNumber(buff[0])) + return EMPTY_VALUE; + + // + return buff[0]; +} + +// +// Create or reuse an RSI handle for the given TF ... +int GetOrCreateRSIHandle( + string symbol, + ENUM_TIMEFRAMES tf, + int period, + int appliedPrice // +) +{ + // + int h = g_rsiHandleH1; + if (tf == PERIOD_H4) + h = g_rsiHandleH4; + else if (tf == PERIOD_D1) + h = g_rsiHandleD1; + if (h == INVALID_HANDLE) + { + h = iRSI(symbol, tf, period, appliedPrice); + if (h == INVALID_HANDLE) + Print("Failed to create RSI handle: ", symbol, " ", EnumToString(tf), " period=", period, " price=", appliedPrice); + } + return h; +} + +// +// Read RSI value for a specific bar shift (1=last closed bar) .. +double GetRSIValue( + string symbol, + ENUM_TIMEFRAMES tf, + int period, + int appliedPrice, + int shift // +) +{ + int h = GetOrCreateRSIHandle(symbol, tf, period, appliedPrice); + if (h == INVALID_HANDLE) + return EMPTY_VALUE; + double buff[]; + int copied = CopyBuffer(h, 0, shift, 1, buff); + if (copied != 1 || !MathIsValidNumber(buff[0])) + return EMPTY_VALUE; + return buff[0]; +} + +datetime GetLastClosedBarTime(string symbol, ENUM_TIMEFRAMES tf) +{ + datetime times[]; + if (CopyTime(symbol, tf, 0, 3, times) <= 1) + return 0; + // times[0] is current open bar time; last closed is times[1] + return times[1]; +} + +bool IsHourInRange(int hr, int startHr, int endHr) +{ + // Handles wrap-around (e.g., 22 -> 6) + if (startHr <= endHr) + return (hr >= startHr && hr < endHr); + else + return (hr >= startHr || hr < endHr); +} + +bool GetXKIStateAndKI(string symbol, ENUM_TIMEFRAMES tf, int shift, int &stateOut, double &kiOut) +{ + // Prepare indicator handle for this TF + static int handleH1 = INVALID_HANDLE; + static int handleH4 = INVALID_HANDLE; + static int handleD1 = INVALID_HANDLE; + + int handleRef = handleH1; + if (tf == PERIOD_H4) + handleRef = handleH4; + else if (tf == PERIOD_D1) + handleRef = handleD1; + + if (handleRef == INVALID_HANDLE) + { + handleRef = iCustom(symbol, tf, g_xkiIndicatorPath, + InpKiLength, InpShowKI, InpCalcLastBars); + if (handleRef == INVALID_HANDLE) + { + Print("Failed to create XKI handle for TF: ", EnumToString(tf)); + return false; + } + } + + double kiBuff[]; + double stateBuff[]; + + if (CopyBuffer(handleRef, KI_BUFFER_INDEX, shift, 1, kiBuff) != 1) + return false; + if (CopyBuffer(handleRef, KI_STATE_BUFFER_INDEX, shift, 1, stateBuff) != 1) + return false; + + kiOut = kiBuff[0]; + stateOut = (int)stateBuff[0]; + + if (!MathIsValidNumber(kiOut)) + return false; + return true; +} + +bool HigherTFAgrees(string symbol, ENUM_TIMEFRAMES tf, int shift, int signalState) +{ + int stateHTF; + double kiHTF; + if (!GetXKIStateAndKI(symbol, tf, shift, stateHTF, kiHTF)) + return false; + if (signalState == BULLISH_STATE) + return (stateHTF == BULLISH_STATE); + if (signalState == BEARISH_STATE) + return (stateHTF == BEARISH_STATE); + return false; +} + +bool HasOpenPosition(string symbol, int magic) +{ + for (int i = 0; i < PositionsTotal(); i++) + { + ulong ticket = PositionGetTicket(i); + if (ticket == 0) + continue; + if (PositionSelectByTicket(ticket)) + { + string sym = PositionGetString(POSITION_SYMBOL); + long mg = (long)PositionGetInteger(POSITION_MAGIC); + if (sym == symbol && mg == magic) + return true; + } + } + return false; +} + +void PlaceOrder(string symbol, ENUM_ORDER_TYPE type, double lots, double sl, double tp) +{ + MqlTradeRequest req; + MqlTradeResult res; + ZeroMemory(req); + ZeroMemory(res); + + double price = 0.0; + if (!SymbolInfoTick(symbol, g_tick)) + return; + + if (type == ORDER_TYPE_BUY) + price = g_tick.ask; + else if (type == ORDER_TYPE_SELL) + price = g_tick.bid; + + // Normalize SL/TP + sl = NormalizeDouble(sl, g_digits); + tp = NormalizeDouble(tp, g_digits); + price = NormalizeDouble(price, g_digits); + + req.action = TRADE_ACTION_DEAL; + req.symbol = symbol; + req.volume = lots; + req.type = type; + req.price = price; + req.sl = sl; + req.tp = tp; + req.deviation = InpSlippagePoints; + req.magic = InpMagic; + req.comment = InpOrderComment; + + if (!OrderSend(req, res)) + Print("OrderSend failed: ", res.retcode); +} + +void TrailStopsByKI() +{ + // Trail per position using current signal TF KI + for (int i = 0; i < PositionsTotal(); i++) + { + ulong ticket = PositionGetTicket(i); + if (ticket == 0) + continue; + if (!PositionSelectByTicket(ticket)) + continue; + + string sym = PositionGetString(POSITION_SYMBOL); + long mg = (long)PositionGetInteger(POSITION_MAGIC); + if (sym != InpSymbol || mg != InpMagic) + continue; + + ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + double sl = PositionGetDouble(POSITION_SL); + double priceOpen = PositionGetDouble(POSITION_PRICE_OPEN); + + // Use last closed bar KI for stability + int shift = 1; + int state; + double ki; + if (!GetXKIStateAndKI(sym, InpSignalTF, shift, state, ki)) + continue; + + MqlTradeRequest req; + MqlTradeResult res; + ZeroMemory(req); + ZeroMemory(res); + + double newSL = sl; + + if (ptype == POSITION_TYPE_BUY) + { + double proposedSL = NormalizeDouble(ki, g_digits); + if (proposedSL > sl) + newSL = proposedSL; // only move up + } + else if (ptype == POSITION_TYPE_SELL) + { + double proposedSL = NormalizeDouble(ki, g_digits); + if (proposedSL < sl || sl == 0.0) + newSL = proposedSL; // only move down (or set if none) + } + + if (newSL != sl && newSL != 0.0) + { + req.action = TRADE_ACTION_SLTP; + req.symbol = sym; + req.sl = newSL; + req.tp = PositionGetDouble(POSITION_TP); + req.magic = InpMagic; + + if (!OrderSend(req, res)) + Print("Trail SLTP failed: ", res.retcode); + } + } +} + +//+------------------------------------------------------------------+ diff --git a/BKPS/14041018/Documents/BKP/XPullbackTradeer.ex5 b/BKPS/14041018/Documents/BKP/XPullbackTradeer.ex5 new file mode 100644 index 0000000..0915596 Binary files /dev/null and b/BKPS/14041018/Documents/BKP/XPullbackTradeer.ex5 differ diff --git a/BKPS/14041018/Documents/BKP/XPullbackTradeer.mq5 b/BKPS/14041018/Documents/BKP/XPullbackTradeer.mq5 new file mode 100644 index 0000000..9692e8b --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XPullbackTradeer.mq5 @@ -0,0 +1,708 @@ +//+------------------------------------------------------------------+ +//| TrendPullbackPro.mq5| +//| Trend-following pullback EA with risk & management | +//+------------------------------------------------------------------+ +#property copyright "Hadi Strategy" +#property link "" +#property version "1.10" +#property strict + +//--- Inputs: risk & money management +input double InpRiskPerTradePercent = 1.0; // Total risk per trade (% of balance) +input int InpMagicNumber = 123456; // Magic number +input double InpStopBufferPoints = 10; // Extra buffer beyond swing high/low (points) + +//--- Inputs: indicators +input ENUM_TIMEFRAMES InpTF = PERIOD_CURRENT; // Signal timeframe +input int InpFastEMAPeriod = 20; +input int InpSlowEMAPeriod = 50; +input int InpRSIPeriod = 14; +input double InpRSILowZoneMin = 40; // Uptrend pullback zone min +input double InpRSILowZoneMax = 50; // Uptrend pullback zone max +input double InpRSIHighZoneMin = 50; // Downtrend pullback zone min +input double InpRSIHighZoneMax = 60; // Downtrend pullback zone max + +//--- Inputs: partial TP and R multiples +input bool InpUsePartialTP = true; +input double InpPartialCloseAtR = 1.0; // R at which to take partial profit +input double InpPartialClosePercent = 50.0; // % of volume to close at partial TP +input double InpFinalTargetR = 3.0; // Final target R for runner +input bool InpUseBreakEven = true; +input double InpBreakEvenRMultiple = 1.0; // Move SL to BE at this R (runner) + +//--- Inputs: trailing stop +input bool InpUseEMATrailing = true; +input double InpTrailStartR = 1.0; // Start trailing after this R +input double InpTrailOffsetPoints = 5; // Extra buffer beyond EMA (points) + +//--- Inputs: spread & time filters +input bool InpUseSpreadFilter = true; +input double InpMaxSpreadPoints = 30; // Max allowed spread (in points) + +input bool InpUseTimeFilter = false; +input int InpSessionStartHour = 8; // Trading session start (server time) +input int InpSessionEndHour = 22; // Trading session end (server time) +input bool InpAvoidRolloverHour = true; +input int InpRolloverHour = 23; // Avoid new entries at this hour + +//--- constants +#define NO_TREND 0 +#define UPTREND 1 +#define DOWNTREND -1 + +#define PARTIAL_COMMENT "TrendPullbackEA_Partial" +#define RUNNER_COMMENT "TrendPullbackEA_Runner" + +//--- Global indicator handles +int rsi_handle; +int ema_fast_handle; +int ema_slow_handle; + +//--- Tick storage +MqlTick last_tick; + +//+------------------------------------------------------------------+ +//| OnInit | +//+------------------------------------------------------------------+ +int OnInit() +{ + rsi_handle = iRSI(_Symbol, InpTF, InpRSIPeriod, PRICE_CLOSE); + if(rsi_handle == INVALID_HANDLE) + { + Print("Error creating RSI handle. Error: ", GetLastError()); + return(INIT_FAILED); + } + + ema_fast_handle = iMA(_Symbol, InpTF, InpFastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); + if(ema_fast_handle == INVALID_HANDLE) + { + Print("Error creating fast EMA handle. Error: ", GetLastError()); + return(INIT_FAILED); + } + + ema_slow_handle = iMA(_Symbol, InpTF, InpSlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); + if(ema_slow_handle == INVALID_HANDLE) + { + Print("Error creating slow EMA handle. Error: ", GetLastError()); + return(INIT_FAILED); + } + + SymbolInfoTick(_Symbol, last_tick); + return(INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| OnDeinit | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + IndicatorRelease(rsi_handle); + IndicatorRelease(ema_fast_handle); + IndicatorRelease(ema_slow_handle); +} + +//+------------------------------------------------------------------+ +//| OnTick | +//+------------------------------------------------------------------+ +void OnTick() +{ + if(!SymbolInfoTick(_Symbol, last_tick)) + return; + + // Run main logic once per bar on signal timeframe + static datetime last_bar_time = 0; + datetime cur_bar_time = iTime(_Symbol, InpTF, 0); + if(cur_bar_time == last_bar_time) + return; + last_bar_time = cur_bar_time; + + ManageOpenPositions(); + + // Avoid new entries if no time/spread conditions + if(!CanOpenNewTrades()) + return; + + CheckOpenSignals(); +} + +//+------------------------------------------------------------------+ +//| Check if we can open new trades (time & spread) | +//+------------------------------------------------------------------+ +bool CanOpenNewTrades() +{ + // Spread filter + if(InpUseSpreadFilter) + { + double spread_points = (SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID)) + / SymbolInfoDouble(_Symbol, SYMBOL_POINT); + if(spread_points > InpMaxSpreadPoints) + { + //Print("Spread too high: ", spread_points, " > ", InpMaxSpreadPoints); + return(false); + } + } + + // Time filter + if(InpUseTimeFilter) + { + datetime now = TimeCurrent(); + MqlDateTime dt; + TimeToStruct(now, dt); + + // avoid rollover hour + if(InpAvoidRolloverHour && dt.hour == InpRolloverHour) + return(false); + + // session window + bool inSession = (dt.hour >= InpSessionStartHour && dt.hour < InpSessionEndHour); + if(!inSession) + return(false); + } + + return(true); +} + +//+------------------------------------------------------------------+ +//| Check for new entry signals | +//+------------------------------------------------------------------+ +void CheckOpenSignals() +{ + if(HasOpenPosition()) + return; + + int trend = GetTrendDirection(); + if(trend == NO_TREND) + return; + + double rsi_value; + if(!GetRSI(1, rsi_value)) + return; + + MqlRates rates[]; + if(CopyRates(_Symbol, InpTF, 0, 3, rates) < 3) + return; + // rates[0] current, [1] closed 1, [2] closed 2 + MqlRates candle = rates[1]; + MqlRates prev = rates[2]; + + bool longSignal = false; + bool shortSignal = false; + + if(trend == UPTREND) + { + if(rsi_value >= InpRSILowZoneMin && rsi_value <= InpRSILowZoneMax) + { + if(IsBullishPattern(candle, prev)) + longSignal = true; + } + } + else if(trend == DOWNTREND) + { + if(rsi_value >= InpRSIHighZoneMin && rsi_value <= InpRSIHighZoneMax) + { + if(IsBearishPattern(candle, prev)) + shortSignal = true; + } + } + + if(longSignal) + OpenTrade(ORDER_TYPE_BUY, candle); + else if(shortSignal) + OpenTrade(ORDER_TYPE_SELL, candle); +} + +//+------------------------------------------------------------------+ +//| Manage open positions (partial TP, BE, trailing) | +//+------------------------------------------------------------------+ +void ManageOpenPositions() +{ + double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); + + for(int i = PositionsTotal()-1; i >= 0; i--) + { + ulong ticket = PositionGetTicket(i); + if(!PositionSelectByTicket(ticket)) + continue; + + if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) + continue; + if(PositionGetString(POSITION_SYMBOL) != _Symbol) + continue; + + long type = PositionGetInteger(POSITION_TYPE); + double volume = PositionGetDouble(POSITION_VOLUME); + double sl = PositionGetDouble(POSITION_SL); + double tp = PositionGetDouble(POSITION_TP); + double price_open = PositionGetDouble(POSITION_PRICE_OPEN); + string comment = PositionGetString(POSITION_COMMENT); + + MqlTick tick; + SymbolInfoTick(_Symbol, tick); + double current_price = (type == POSITION_TYPE_BUY ? tick.bid : tick.ask); + + double riskPoints; + if(type == POSITION_TYPE_BUY) + riskPoints = (price_open - sl) / point; + else + riskPoints = (sl - price_open) / point; + + if(riskPoints <= 0) + continue; + + double profitPoints; + if(type == POSITION_TYPE_BUY) + profitPoints = (current_price - price_open) / point; + else + profitPoints = (price_open - current_price) / point; + + double rMultiple = profitPoints / riskPoints; + + // 1) Partial TP logic for "partial" leg + if(InpUsePartialTP && comment == PARTIAL_COMMENT) + { + if(rMultiple >= InpPartialCloseAtR) + { + // Close this position fully (it's the partial leg) + ClosePosition(ticket); + continue; + } + } + + // 2) Break-even & trailing for runner leg + if(comment == RUNNER_COMMENT) + { + // Break-even + if(InpUseBreakEven && rMultiple >= InpBreakEvenRMultiple) + { + if(type == POSITION_TYPE_BUY && sl < price_open) + ModifyPositionSL(ticket, price_open); + else if(type == POSITION_TYPE_SELL && sl > price_open) + ModifyPositionSL(ticket, price_open); + } + + // EMA trailing after a certain R + if(InpUseEMATrailing && rMultiple >= InpTrailStartR) + { + double emaFast; + if(!GetEMA(ema_fast_handle, 1, emaFast)) + continue; + + double newSL; + double offset = InpTrailOffsetPoints * point; + if(type == POSITION_TYPE_BUY) + { + newSL = emaFast - offset; + if(newSL > sl && newSL < current_price) // only tighten SL + ModifyPositionSL(ticket, newSL); + } + else + { + newSL = emaFast + offset; + if(newSL < sl && newSL > current_price) + ModifyPositionSL(ticket, newSL); + } + } + + // Optionally: ensure TP aligns with final target R + // If user wants to rely only on trailing, they can disable or adjust final R. + // We keep TP as set at entry. + } + } +} + +//+------------------------------------------------------------------+ +//| Get trend direction from EMAs | +//+------------------------------------------------------------------+ +int GetTrendDirection() +{ + double ema_fast[3], ema_slow[3]; + if(CopyBuffer(ema_fast_handle, 0, 0, 3, ema_fast) < 3) + return NO_TREND; + if(CopyBuffer(ema_slow_handle, 0, 0, 3, ema_slow) < 3) + return NO_TREND; + + double fast = ema_fast[1]; + double slow = ema_slow[1]; + + if(fast > slow) + return UPTREND; + else if(fast < slow) + return DOWNTREND; + return NO_TREND; +} + +//+------------------------------------------------------------------+ +//| Get RSI value at bar index | +//+------------------------------------------------------------------+ +bool GetRSI(int index, double &value) +{ + double buffer[1]; + int copied = CopyBuffer(rsi_handle, 0, index, 1, buffer); + if(copied != 1) + return false; + + value = buffer[0]; + return true; +} + +//+------------------------------------------------------------------+ +//| Get EMA value from handle | +//+------------------------------------------------------------------+ +bool GetEMA(int handle, int index, double &value) +{ + double buffer[1]; + int copied = CopyBuffer(handle, 0, index, 1, buffer); + if(copied != 1) + return false; + value = buffer[0]; + return true; +} + +//+------------------------------------------------------------------+ +//| Bullish pattern: engulfing + pin-bar-ish | +//+------------------------------------------------------------------+ +bool IsBullishPattern(const MqlRates &c, const MqlRates &prev) +{ + double bodyC = MathAbs(c.close - c.open); + double bodyP = MathAbs(prev.close - prev.open); + double rangeC = c.high - c.low; + + if(rangeC <= 0) + return false; + + // Basic bullish: close > open + if(c.close <= c.open) + return false; + + // Engulfing body: current body >= previous body, and covers its open/close + bool engulfing = (bodyC >= bodyP && c.open <= prev.close && c.close >= prev.open); + + // Pin-bar-ish: long lower wick + double lowerWick = MathMin(c.open, c.close) - c.low; + bool longLowerWick = (lowerWick >= rangeC * 0.4); // tweak + + if(engulfing || longLowerWick) + return true; + + return false; +} + +//+------------------------------------------------------------------+ +//| Bearish pattern: engulfing + pin-bar-ish | +//+------------------------------------------------------------------+ +bool IsBearishPattern(const MqlRates &c, const MqlRates &prev) +{ + double bodyC = MathAbs(c.close - c.open); + double bodyP = MathAbs(prev.close - prev.open); + double rangeC = c.high - c.low; + + if(rangeC <= 0) + return false; + + // Basic bearish: close < open + if(c.close >= c.open) + return false; + + // Engulfing body + bool engulfing = (bodyC >= bodyP && c.open >= prev.close && c.close <= prev.open); + + // Pin-bar-ish: long upper wick + double upperWick = c.high - MathMax(c.open, c.close); + bool longUpperWick = (upperWick >= rangeC * 0.4); // tweak + + if(engulfing || longUpperWick) + return true; + + return false; +} + +//+------------------------------------------------------------------+ +//| Check if there is already an open position | +//+------------------------------------------------------------------+ +bool HasOpenPosition() +{ + for(int i = PositionsTotal()-1; i >= 0; i--) + { + ulong ticket = PositionGetTicket(i); + if(!PositionSelectByTicket(ticket)) + continue; + + if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) + continue; + + if(PositionGetString(POSITION_SYMBOL) == _Symbol) + return true; + } + return false; +} + +//+------------------------------------------------------------------+ +//| Calculate lot size based on total risk % | +//+------------------------------------------------------------------+ +double CalculateTotalVolume(double stopLossPrice, ENUM_ORDER_TYPE type) +{ + double balance = AccountInfoDouble(ACCOUNT_BALANCE); + double riskMoney = balance * InpRiskPerTradePercent / 100.0; + + double entryPrice = (type == ORDER_TYPE_BUY ? last_tick.ask : last_tick.bid); + + double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); + double tick_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); + double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); + + if(tick_size <= 0 || tick_value <= 0) + return(0.0); + + double slDistance = (type == ORDER_TYPE_BUY ? entryPrice - stopLossPrice : stopLossPrice - entryPrice); + if(slDistance <= 0) + return(0.0); + + double moneyPerPointPerLot = tick_value / tick_size * point; + double stopPoints = slDistance / point; + + double volume = riskMoney / (stopPoints * moneyPerPointPerLot); + + double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); + double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); + double lotStep= SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); + + volume = MathFloor(volume / lotStep) * lotStep; + + if(volume < minLot) + volume = 0.0; + if(volume > maxLot) + volume = maxLot; + + return(volume); +} + +//+------------------------------------------------------------------+ +//| Open trade: split into partial + runner | +//+------------------------------------------------------------------+ +void OpenTrade(ENUM_ORDER_TYPE type, const MqlRates &signalCandle) +{ + MqlTick tick; + if(!SymbolInfoTick(_Symbol, tick)) + return; + + double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); + double entryPrice = (type == ORDER_TYPE_BUY ? tick.ask : tick.bid); + + double slPrice; + if(type == ORDER_TYPE_BUY) + slPrice = signalCandle.low - InpStopBufferPoints * point; + else + slPrice = signalCandle.high + InpStopBufferPoints * point; + + if(slPrice <= 0) + return; + + double totalVolume = CalculateTotalVolume(slPrice, type); + if(totalVolume <= 0) + { + Print("Calculated total volume <= 0, skipping trade."); + return; + } + + double slDistance = (type == ORDER_TYPE_BUY ? entryPrice - slPrice : slPrice - entryPrice); + + // final TP at FinalTargetR + double finalTPDistance = slDistance * InpFinalTargetR; + double runnerTP; + if(type == ORDER_TYPE_BUY) + runnerTP = entryPrice + finalTPDistance; + else + runnerTP = entryPrice - finalTPDistance; + + // partial volume + double partialVolume = totalVolume; + double runnerVolume = 0.0; + + if(InpUsePartialTP && InpPartialClosePercent > 0 && InpPartialClosePercent < 100) + { + partialVolume = totalVolume * (InpPartialClosePercent / 100.0); + runnerVolume = totalVolume - partialVolume; + } + else + { + // no partial: everything is runner + partialVolume = 0.0; + runnerVolume = totalVolume; + } + + // normalized volumes + double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); + partialVolume = MathFloor(partialVolume / lotStep) * lotStep; + runnerVolume = MathFloor(runnerVolume / lotStep) * lotStep; + + if(partialVolume < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) + partialVolume = 0.0; + if(runnerVolume < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) + runnerVolume = 0.0; + + // Partial TP price at PartialCloseAtR + double partialTPPrice = 0.0; + if(InpUsePartialTP && partialVolume > 0 && InpPartialCloseAtR > 0) + { + double partialTPDist = slDistance * InpPartialCloseAtR; + if(type == ORDER_TYPE_BUY) + partialTPPrice = entryPrice + partialTPDist; + else + partialTPPrice = entryPrice - partialTPDist; + } + + // 1) Open partial leg + if(partialVolume > 0.0) + { + SendOrder(type, partialVolume, slPrice, partialTPPrice, PARTIAL_COMMENT); + } + + // 2) Open runner leg + if(runnerVolume > 0.0) + { + SendOrder(type, runnerVolume, slPrice, runnerTP, RUNNER_COMMENT); + } +} + +//+------------------------------------------------------------------+ +//| Send market order | +//+------------------------------------------------------------------+ +bool SendOrder(ENUM_ORDER_TYPE type, double volume, double sl, double tp, string comment) +{ + if(volume <= 0.0) + return(false); + + MqlTick tick; + if(!SymbolInfoTick(_Symbol, tick)) + return(false); + + MqlTradeRequest request; + MqlTradeResult result; + ZeroMemory(request); + ZeroMemory(result); + + request.action = TRADE_ACTION_DEAL; + request.magic = InpMagicNumber; + request.symbol = _Symbol; + request.volume = volume; + request.type = type; + request.deviation = 20; // points + request.type_filling= ORDER_FILLING_FOK; + request.price = (type == ORDER_TYPE_BUY ? tick.ask : tick.bid); + request.sl = sl; + request.tp = tp; + request.comment = comment; + + if(!OrderSend(request, result)) + { + Print("OrderSend failed. Error: ", GetLastError()); + return(false); + } + if(result.retcode != TRADE_RETCODE_DONE) + { + Print("OrderSend retcode: ", result.retcode); + return(false); + } + + Print("Opened ", (type == ORDER_TYPE_BUY ? "BUY" : "SELL"), + " ticket #", result.order, " vol=", DoubleToString(volume,2), + " SL=", DoubleToString(sl,_Digits)," TP=", DoubleToString(tp,_Digits), + " comment=", comment); + return(true); +} + +//+------------------------------------------------------------------+ +//| Modify SL for position | +//+------------------------------------------------------------------+ +bool ModifyPositionSL(ulong ticket, double newSL) +{ + if(!PositionSelectByTicket(ticket)) + return(false); + + string sym = PositionGetString(POSITION_SYMBOL); + long type = PositionGetInteger(POSITION_TYPE); + double volume = PositionGetDouble(POSITION_VOLUME); + double price = PositionGetDouble(POSITION_PRICE_OPEN); + double tp = PositionGetDouble(POSITION_TP); + + MqlTradeRequest request; + MqlTradeResult result; + ZeroMemory(request); + ZeroMemory(result); + + request.action = TRADE_ACTION_SLTP; + request.magic = InpMagicNumber; + request.symbol = sym; + request.volume = volume; + request.type = (ENUM_ORDER_TYPE)type; + request.price = price; + request.sl = newSL; + request.tp = tp; + + if(!OrderSend(request, result)) + { + Print("ModifyPositionSL OrderSend failed. Error: ", GetLastError()); + return(false); + } + if(result.retcode != TRADE_RETCODE_DONE) + { + Print("ModifyPositionSL retcode: ", result.retcode); + return(false); + } + + Print("Modified SL for ticket #", ticket, " to ", DoubleToString(newSL,_Digits)); + return(true); +} + +//+------------------------------------------------------------------+ +//| Close position | +//+------------------------------------------------------------------+ +bool ClosePosition(ulong ticket) +{ + if(!PositionSelectByTicket(ticket)) + return(false); + + string sym = PositionGetString(POSITION_SYMBOL); + long type = PositionGetInteger(POSITION_TYPE); + double volume = PositionGetDouble(POSITION_VOLUME); + double price = 0.0; + + MqlTick tick; + if(!SymbolInfoTick(sym, tick)) + return(false); + + if(type == POSITION_TYPE_BUY) + price = tick.bid; + else + price = tick.ask; + + MqlTradeRequest request; + MqlTradeResult result; + ZeroMemory(request); + ZeroMemory(result); + + request.action = TRADE_ACTION_DEAL; + request.magic = InpMagicNumber; + request.symbol = sym; + request.volume = volume; + request.type = (type == POSITION_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY); + request.price = price; + request.deviation = 20; + request.type_filling= ORDER_FILLING_FOK; + request.comment = "Close"; + + if(!OrderSend(request, result)) + { + Print("ClosePosition OrderSend failed. Error: ", GetLastError()); + return(false); + } + if(result.retcode != TRADE_RETCODE_DONE) + { + Print("ClosePosition retcode: ", result.retcode); + return(false); + } + + Print("Closed ticket #", ticket); + return(true); +} +//+------------------------------------------------------------------+ diff --git a/BKPS/14041018/Documents/BKP/XZoneEa.ex5 b/BKPS/14041018/Documents/BKP/XZoneEa.ex5 new file mode 100644 index 0000000..23d7ff5 Binary files /dev/null and b/BKPS/14041018/Documents/BKP/XZoneEa.ex5 differ diff --git a/BKPS/14041018/Documents/BKP/XZoneEa.mq5 b/BKPS/14041018/Documents/BKP/XZoneEa.mq5 new file mode 100644 index 0000000..cbf151b --- /dev/null +++ b/BKPS/14041018/Documents/BKP/XZoneEa.mq5 @@ -0,0 +1,525 @@ +//+------------------------------------------------------------------+ +//| XRR_Pullback.mq5 | +//| Author: Hadi (for XAUUSD,M15) | +//+------------------------------------------------------------------+ +#property strict +#property version "0.1" +#property description "M15 pullback EA: Major zone (HH/LL), minor same-direction zone, pullback entry, SL under minor, TP at 2R, 1% risk." + +//------------------------------- Inputs ----------------------------- + +input string Inp_Symbol = "XAUUSD"; +input ENUM_TIMEFRAMES Inp_WorkTF = PERIOD_M15; + +// Zone detection params +input int Inp_MajorLookbackBars = 400; // bars to scan for HH/LL major zone +input int Inp_MinorWindowBars = 80; // window to find first same-direction minor zone post-major +input int Inp_ZonePadPoints = 50; // padding around zones (points) + +// Confirmation / filters +input bool Inp_UseHTFConfluence = true; +input ENUM_TIMEFRAMES Inp_HTF = PERIOD_H1; // confluence timeframe +input int Inp_HTFShiftBars = 3; // HTF confirmation window +input bool Inp_UseEngulfingConfirm = true; +input bool Inp_UseRSIDivergence = false; +input int Inp_RSI_Period = 14; +input bool Inp_UseVolumeSpike = false; +input double Inp_VolSpikeFactor = 1.5; // vs 20-bar average + +// Risk management +input double Inp_RiskPercent = 1.0; // 1% per trade +input bool Inp_UseATRforSL = false; +input int Inp_ATR_Period = 14; +input double Inp_ATR_Mult = 1.5; +input double Inp_MinSLPoints = 200; // floor SL (points) +input double Inp_R_MultipleTP = 2.0; // fixed R:R=1:2 + +// Risk-free (optional) +input bool Inp_MoveToBEatTP1 = true; +input double Inp_TP1_R = 1.0; // move to BE at 1R +input double Inp_BE_OffsetPoints = 10; // lock-in small +offset + +// Sessions +input bool Inp_UseSessionFilter = true; +input int Inp_LondonOpenHour = 8; // broker time +input int Inp_LondonCloseHour = 17; +input int Inp_NYOpenHour = 13; +input int Inp_NYCloseHour = 21; +input bool Inp_AllowNYOverlapOnly = false; + +// Entry placement +input bool Inp_UseLimitAtZone = true; // limit order at minor zone +input int Inp_MaxSlippagePoints = 100; +input int Inp_MinRetestWickPoints = 30; + +// Safety / engine +input int Inp_MinBarsLoaded = 600; +input int Inp_SignalCoolOffBars = 20; // avoid rapid re-entries +input bool Inp_OnePositionOnly = true; + +//------------------------------- Structures ------------------------- +struct Zone +{ + bool isValid; + double priceLow; + double priceHigh; + int barIndex; // starting bar index of zone + bool isSupply; // true: resistance (HH), false: support (LL) +}; + +struct MinorZone +{ + bool isValid; + double priceLow; + double priceHigh; + int barIndex; + bool isSupply; // same direction as major +}; + +datetime lastSignalTimeBuy = 0; +datetime lastSignalTimeSell = 0; + +// +int atrHandler = INVALID_HANDLE; + +//------------------------------- Helpers ---------------------------- +int DigitsAdjust() +{ + return (int)SymbolInfoInteger(Inp_Symbol, SYMBOL_DIGITS); +} +double PointAdjust() +{ + return SymbolInfoDouble(Inp_Symbol, SYMBOL_POINT); +} +double TickValue() +{ + double v; + SymbolInfoDouble(Inp_Symbol, SYMBOL_TRADE_TICK_VALUE, v); + return v; +} +double TickSize() +{ + double s; + SymbolInfoDouble(Inp_Symbol, SYMBOL_TRADE_TICK_SIZE, s); + return s; +} + +bool IsSessionAllowed() +{ + if (!Inp_UseSessionFilter) + return true; + MqlDateTime t; + TimeToStruct(TimeCurrent(), t); + int hour = t.hour; + bool london = (hour >= Inp_LondonOpenHour && hour < Inp_LondonCloseHour); + bool ny = (hour >= Inp_NYOpenHour && hour < Inp_NYCloseHour); + if (Inp_AllowNYOverlapOnly) + return (london && ny); + return (london || ny); +} + +bool EngulfingBearish(int shift) +{ + double o0 = iOpen(Inp_Symbol, Inp_WorkTF, shift), c0 = iClose(Inp_Symbol, Inp_WorkTF, shift); + double o1 = iOpen(Inp_Symbol, Inp_WorkTF, shift + 1), c1 = iClose(Inp_Symbol, Inp_WorkTF, shift + 1); + return (c0 < o0 && c1 > o1 && o0 < c1 && c0 < o1 && (o0 - o1) > 0 && (c1 - c0) > 0 && (o1 < c0)); // rough engulfing +} +bool EngulfingBullish(int shift) +{ + double o0 = iOpen(Inp_Symbol, Inp_WorkTF, shift), c0 = iClose(Inp_Symbol, Inp_WorkTF, shift); + double o1 = iOpen(Inp_Symbol, Inp_WorkTF, shift + 1), c1 = iClose(Inp_Symbol, Inp_WorkTF, shift + 1); + return (c0 > o0 && c1 < o1 && o0 > c1 && c0 > o1 && (o0 - o1) > 0 && (c0 - c1) > 0 && (o1 > c0)); // rough engulfing inverse +} + +bool VolumeSpike(int shift) +{ + if (!Inp_UseVolumeSpike) + return true; + double avg = 0; + int n = 20; + for (int i = shift + 1; i < shift + 1 + n; i++) + avg += (double)iVolume(Inp_Symbol, Inp_WorkTF, i); + avg /= n; + double v0 = (double)iVolume(Inp_Symbol, Inp_WorkTF, shift); + return (v0 >= avg * Inp_VolSpikeFactor); +} + +bool HTFConfluence(bool wantSupply) +{ + if (!Inp_UseHTFConfluence) + return true; + // Simple HTF direction: last HTF candle close vs open + double o = iOpen(Inp_Symbol, Inp_HTF, Inp_HTFShiftBars), c = iClose(Inp_Symbol, Inp_HTF, Inp_HTFShiftBars); + bool htfDown = (c < o), htfUp = (c > o); + return wantSupply ? htfDown : htfUp; +} + +//------------------------------- Zone detection --------------------- +Zone FindMajorZone() +{ + Zone z; + z.isValid = false; + z.isSupply = false; + z.priceLow = 0; + z.priceHigh = 0; + z.barIndex = -1; + int bars = iBars(Inp_Symbol, Inp_WorkTF); + if (bars < Inp_MinBarsLoaded) + return z; + + // Highest high / lowest low over lookback + double hh = -DBL_MAX, ll = DBL_MAX; + int hhBar = -1, llBar = -1; + for (int i = 1; i <= Inp_MajorLookbackBars; i++) + { + double h = iHigh(Inp_Symbol, Inp_WorkTF, i), l = iLow(Inp_Symbol, Inp_WorkTF, i); + if (h > hh) + { + hh = h; + hhBar = i; + } + if (l < ll) + { + ll = l; + llBar = i; + } + } + + // Decide which one is closest to current action: use most recent extreme + if (hhBar < llBar) + { + z.isSupply = true; + z.isValid = true; + z.barIndex = hhBar; + z.priceLow = hh - Inp_ZonePadPoints * PointAdjust(); + z.priceHigh = hh + Inp_ZonePadPoints * PointAdjust(); + } + else + { + z.isSupply = false; + z.isValid = true; + z.barIndex = llBar; + z.priceLow = ll - Inp_ZonePadPoints * PointAdjust(); + z.priceHigh = ll + Inp_ZonePadPoints * PointAdjust(); + } + return z; +} + +MinorZone FindFirstMinorSameDirection(const Zone &major) +{ + MinorZone mz; + mz.isValid = false; + mz.isSupply = major.isSupply; + mz.priceLow = 0; + mz.priceHigh = 0; + mz.barIndex = -1; + if (!major.isValid) + return mz; + + // Scan forward from major's bar toward current for first reaction zone aligned with major + int start = major.barIndex - 1; + int end = MathMax(1, start - Inp_MinorWindowBars); + + // Heuristic: supply minor = bearish impulse followed by base; demand minor = bullish impulse followed by base + for (int i = start; i >= end; i--) + { + double o = iOpen(Inp_Symbol, Inp_WorkTF, i), c = iClose(Inp_Symbol, Inp_WorkTF, i); + double h = iHigh(Inp_Symbol, Inp_WorkTF, i), l = iLow(Inp_Symbol, Inp_WorkTF, i); + + bool bearImpulse = (c < o && (o - c) > (h - l) * 0.5); + bool bullImpulse = (c > o && (c - o) > (h - l) * 0.5); + + if (major.isSupply && bearImpulse) + { + // Base zone from next candle tight range + double h1 = iHigh(Inp_Symbol, Inp_WorkTF, i - 1), l1 = iLow(Inp_Symbol, Inp_WorkTF, i - 1); + mz.isValid = true; + mz.barIndex = i - 1; + mz.priceLow = l1 - Inp_ZonePadPoints * PointAdjust(); + mz.priceHigh = h1 + Inp_ZonePadPoints * PointAdjust(); + break; + } + if (!major.isSupply && bullImpulse) + { + double h1 = iHigh(Inp_Symbol, Inp_WorkTF, i - 1), l1 = iLow(Inp_Symbol, Inp_WorkTF, i - 1); + mz.isValid = true; + mz.barIndex = i - 1; + mz.priceLow = l1 - Inp_ZonePadPoints * PointAdjust(); + mz.priceHigh = h1 + Inp_ZonePadPoints * PointAdjust(); + break; + } + } + return mz; +} + +//------------------------------- Signal logic ----------------------- +bool PriceRetestedZone(const MinorZone &mz, bool supply, int shift = 0) +{ + if (!mz.isValid) + return false; + double high = iHigh(Inp_Symbol, Inp_WorkTF, shift), low = iLow(Inp_Symbol, Inp_WorkTF, shift); + // For supply: retest when high touches zone; for demand: retest when low touches zone + if (supply) + return (high >= mz.priceLow && high <= mz.priceHigh && (high - iClose(Inp_Symbol, Inp_WorkTF, shift)) * 1.0 / PointAdjust() >= Inp_MinRetestWickPoints); + else + return (low <= mz.priceHigh && low >= mz.priceLow && (iClose(Inp_Symbol, Inp_WorkTF, shift) - low) * 1.0 / PointAdjust() >= Inp_MinRetestWickPoints); +} + +bool ConfirmAtZone(bool supply) +{ + int shift = 0; + if (Inp_UseEngulfingConfirm) + { + if (supply) + { + if (!EngulfingBearish(shift)) + return false; + } + else + { + if (!EngulfingBullish(shift)) + return false; + } + } + if (!VolumeSpike(shift)) + return false; + if (!HTFConfluence(supply)) + return false; + // Optional: RSI divergence could be added here if enabled. + return true; +} + +//------------------------------- Risk & orders ----------------------- +double CalcPositionSize(double sl_points) +{ + double riskMoney = AccountInfoDouble(ACCOUNT_BALANCE) * (Inp_RiskPercent / 100.0); + double tickValue = TickValue(); + double tickSize = TickSize(); + // Convert SL points to quoted ticks + double ticks = sl_points * PointAdjust() / tickSize; + if (ticks <= 0.0) + return 0.0; + double lots = riskMoney / (ticks * tickValue); + // Normalize to symbol step + double minLot = SymbolInfoDouble(Inp_Symbol, SYMBOL_VOLUME_MIN); + double lotStep = SymbolInfoDouble(Inp_Symbol, SYMBOL_VOLUME_STEP); + double maxLot = SymbolInfoDouble(Inp_Symbol, SYMBOL_VOLUME_MAX); + lots = MathFloor(lots / lotStep) * lotStep; + lots = MathMax(minLot, MathMin(lots, maxLot)); + return lots; +} + +bool PlaceEntry(const MinorZone &mz, bool supply) +{ + double bid = SymbolInfoDouble(Inp_Symbol, SYMBOL_BID); + double ask = SymbolInfoDouble(Inp_Symbol, SYMBOL_ASK); + double point = PointAdjust(); + + // SL beneath/above minor zone (or ATR-based) + double sl, entry, tp; + double sl_points; + + if (supply) + { + entry = Inp_UseLimitAtZone ? mz.priceLow : bid; // sell near zone top/low + double baseSL = mz.priceHigh + Inp_ZonePadPoints * point; + if (Inp_UseATRforSL) + { + // + double atrs[]; + CopyBuffer(atrHandler, MAIN_LINE, 0, 1, atrs); + double atr = atrs[0]; + baseSL = MathMax(baseSL, entry + (atr * Inp_ATR_Mult)); + } + sl = baseSL; + sl_points = (sl - entry) / point; + sl_points = MathMax(sl_points, Inp_MinSLPoints); + tp = entry - (sl_points * point * Inp_R_MultipleTP); + // Position sizing + double lots = CalcPositionSize(sl_points); + if (lots <= 0) + return false; + + MqlTradeRequest req; + MqlTradeResult res; + ZeroMemory(req); + ZeroMemory(res); + req.action = TRADE_ACTION_DEAL; + req.symbol = Inp_Symbol; + req.type = ORDER_TYPE_SELL; + req.volume = lots; + req.price = Inp_UseLimitAtZone ? entry : bid; + req.sl = sl; + req.tp = tp; + req.deviation = Inp_MaxSlippagePoints; + bool ok = OrderSend(req, res); + if (ok) + { + lastSignalTimeSell = TimeCurrent(); + } + return ok; + } + else + { + entry = Inp_UseLimitAtZone ? mz.priceHigh : ask; // buy near zone top/high + double baseSL = mz.priceLow - Inp_ZonePadPoints * point; + if (Inp_UseATRforSL) + { + // + double atrs[]; + CopyBuffer(atrHandler, MAIN_LINE, 0, 1, atrs); + double atr = atrs[0]; + baseSL = MathMin(baseSL, entry - (atr * Inp_ATR_Mult)); + } + sl = baseSL; + sl_points = (entry - sl) / point; + sl_points = MathMax(sl_points, Inp_MinSLPoints); + tp = entry + (sl_points * point * Inp_R_MultipleTP); + double lots = CalcPositionSize(sl_points); + if (lots <= 0) + return false; + + MqlTradeRequest req; + MqlTradeResult res; + ZeroMemory(req); + ZeroMemory(res); + req.action = TRADE_ACTION_DEAL; + req.symbol = Inp_Symbol; + req.type = ORDER_TYPE_BUY; + req.volume = lots; + req.price = Inp_UseLimitAtZone ? entry : ask; + req.sl = sl; + req.tp = tp; + req.deviation = Inp_MaxSlippagePoints; + bool ok = OrderSend(req, res); + if (ok) + { + lastSignalTimeBuy = TimeCurrent(); + } + return ok; + } +} + +//------------------------------- Position management ---------------- +void ManageOpenPositions() +{ + int total = PositionsTotal(); + double point = PointAdjust(); + + for (int i = 0; i < total; i++) + { + string sym = PositionGetSymbol(i); + if (sym != Inp_Symbol) + continue; + if (!PositionSelect(sym)) + continue; + + long type = (long)PositionGetInteger(POSITION_TYPE); + double price = PositionGetDouble(POSITION_PRICE_OPEN); + double sl = PositionGetDouble(POSITION_SL); + double tp = PositionGetDouble(POSITION_TP); + double current = (type == POSITION_TYPE_BUY) ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK); + + // Risk-free move to BE at TP1 (= 1R) + if (Inp_MoveToBEatTP1 && tp > 0 && sl > 0) + { + double rDist = MathAbs(tp - price) / Inp_R_MultipleTP; + bool hitTP1 = (type == POSITION_TYPE_BUY ? (current >= price + rDist) : (current <= price - rDist)); + + if (hitTP1) + { + double newSL = (type == POSITION_TYPE_BUY ? price + Inp_BE_OffsetPoints * point : price - Inp_BE_OffsetPoints * point); + if ((type == POSITION_TYPE_BUY && newSL > sl) || (type == POSITION_TYPE_SELL && newSL < sl)) + { + MqlTradeRequest req; + MqlTradeResult res; + ZeroMemory(req); + ZeroMemory(res); + req.action = TRADE_ACTION_SLTP; + req.symbol = sym; + req.position = (ulong)PositionGetInteger(POSITION_TICKET); + req.sl = newSL; + req.tp = tp; + OrderSend(req, res); + } + } + } + } +} + +//------------------------------- Engine ------------------------------ +bool CoolOffOk(bool supply) +{ + datetime last = supply ? lastSignalTimeSell : lastSignalTimeBuy; + if (last == 0) + return true; + // Convert bars to seconds approximate using last M15 duration + int seconds = Inp_SignalCoolOffBars * 15 * 60; + return (TimeCurrent() - last) >= seconds; +} + +void TrySignal() +{ + if (!IsSessionAllowed()) + return; + + Zone major = FindMajorZone(); + if (!major.isValid) + return; + + MinorZone minor = FindFirstMinorSameDirection(major); + if (!minor.isValid) + return; + + // Only act on retest + confirmation + bool retest = PriceRetestedZone(minor, major.isSupply, 0); + if (!retest) + return; + if (!ConfirmAtZone(major.isSupply)) + return; + if (Inp_OnePositionOnly && PositionsTotal() > 0) + return; + + if (!CoolOffOk(major.isSupply)) + return; + + PlaceEntry(minor, major.isSupply); +} + +//------------------------------- Standard events -------------------- +int OnInit() +{ + // + if (Symbol() != Inp_Symbol) + { + SymbolSelect(Inp_Symbol, true); + } + + // + atrHandler = iATR(Inp_Symbol, Inp_WorkTF, Inp_ATR_Period); + return (INIT_SUCCEEDED); +} + +void OnDeinit(const int reason) +{ +} + +void OnTick() +{ + static datetime lastBarTime = 0; + MqlRates rates[]; + int copied = CopyRates(Inp_Symbol, Inp_WorkTF, 0, Inp_MinBarsLoaded, rates); + if (copied < Inp_MinBarsLoaded) + return; + + datetime curBarTime = rates[0].time; + if (curBarTime != lastBarTime) + { + // New bar on M15: evaluate signal + TrySignal(); + lastBarTime = curBarTime; + } + + // Manage open positions continuously + ManageOpenPositions(); +} diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/TestRegresser.mq5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/TestRegresser.mq5 new file mode 100644 index 0000000..6b54b00 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/TestRegresser.mq5 @@ -0,0 +1,1108 @@ +//+------------------------------------------------------------------+ +//| TestRegresser.mq5 | +//| SaherElm IT Center | +//| https://www.saherelm.ir | +//+------------------------------------------------------------------+ +#property copyright "SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" + +// +// Imports ... +#include "../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include + +// +// Inputs ... + +// +// Calculation ... +input int zigzagDepth = 12; // Depth +input int zigzagDeviation = 5; // Deviation +input int zigzagBackStep = 3; // Back Step +input int mLoopbackLength = 200; // Loopback Length for Calculation +input int mRequiredPivots = 50; // Required Peaks for Calculation (0 > use loopback ) + +// +// Variables ... + +// +double mZigZagBuffer[]; // ZigZag Values Buffer ... +XBarTracker mBarTracker; // Bar Tracker ... +bool mZigZagPivotIsPeaks[]; // Check ZigZag Pivot Peak or Vale ... +double mZigZagPivotPrices[]; // ZigZag Pivot Prices ... +double mZigZagPivotIndexes[]; // ZigZag Pivot Indexes ... +datetime mZigZagPivotTimes[]; // ZigZag Pivot Times ... +CChartObjectTrend *mUpperTrend; // Trend Line Upper ... +CChartObjectTrend *mLowerTrend; // Trend Line Lower ... +int mZigZagHandler = INVALID_HANDLE; // ZigZag Indicator Handler ... + +// +double mPeakSlope; +double mPeakIntercept; +double mZigZagPeaks[]; +double mZigZagPeakIndexes[]; +datetime mZigZagPeakTimes[]; + +// +double mValeSlope; +double mValeIntercept; +double mZigZagVales[]; +double mZigZagValeIndexes[]; +datetime mZigZagValeTimes[]; + +// +datetime mToTime; +datetime mFromTime; + +// +// Predictions ... + +// +double mPeakTo; +double mValeTo; +double mPeakFrom; +double mValeFrom; + +// +ENUM_X_DIRECTION mUpperTrendDir; +ENUM_X_DIRECTION mLowerTrendDir; + +// +// Support and Resistances ... + +// +XBoxZone mSupportBox; +double mMinorSupport; +double mMajorSupport; +XCBoxObject *mSupportObj; + +// +XBoxZone mResistanceBox; +double mMinorResistance; +double mMajorResistance; +XCBoxObject *mResistanceObj; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + // Initialize Bar Tracker ... + mBarTracker.Init( + _Symbol, + _Period // + ); + + // + // Initialize ZigZag Handler ... + mZigZagHandler = iCustom( + _Symbol, + _Period, + "ZigZag", + zigzagDepth, + zigzagDeviation, + zigzagBackStep // + ); + if (mZigZagHandler == INVALID_HANDLE) + { + Print("Error creating ZigZag handle"); + return (INIT_FAILED); + } + + // + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + IndicatorRelease(mZigZagHandler); +} +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // + if (!mBarTracker.IsNewBar()) + { + return; + } + + // + int readedZigZagsCount = 0; + bool readZigZagsBasedOnPivots = mRequiredPivots > 0; + + // + // Reading ZigZag Values Based on Loopback Length ... + if (!readZigZagsBasedOnPivots) + { + readedZigZagsCount = ReadZigZagValues(); + } + // + // Reading ZigZag Pivots based on required Pivots ... + else + { + // + readedZigZagsCount = ReadingZigZagPivots( + 0, // BarIndex ... + mRequiredPivots, // Required Pivots ... + 1500 // Max Allowed Loopback Length ... + ); + } + + // + // Validate Reading Succeed ... + if (readedZigZagsCount <= 0) + { + return; + } + + // + // Try to Detect ZigZag Peaks and Vales ... + ProcessZigZagsPeaksAndVales(); + + // + // Try to Calculate ZigZag Supports and Resistances ... + ProcessZigZagsSupportsAnsResistances(); + + // + // Try to Calculate Peaks and Vales Linear Regression Based + // Slope and Intercept (s) and also Detect From and To Times then + // Predict Peaks and Vales Values for them then ... + // Prepare Support and Resistance Boxes based on Calculated Support + // and Resistances ... + if (!CalculateZigZagLinearRegressionParameters()) + { + return; + } + + // + // Draw Peaks and Vales Based Trend Lines ... + DrawAnalysis(); + + // + // Process ZigZag Values ... + Print(""); + + // +} +//+------------------------------------------------------------------+ + +// +int ReadZigZagValues(int barIndex = 0) +{ + // + int result = 0; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + if (mZigZagHandler == INVALID_HANDLE) + { + return result; + } + + // + // Copy ZigZag Values to Buffers ... + result = CopyBuffer(mZigZagHandler, MAIN_LINE, 0, mLoopbackLength, mZigZagBuffer); + + // + // Set ZigZag Buffers as Series ... + ArraySetAsSeries(mZigZagBuffer, true); + + // + if (result <= 0) + { + return result; + } + + // + // Filling ZigZag Pivots ... + + // + // Clean Buffers ... + SpecifiedClean(mZigZagPivotTimes); + SpecifiedClean(mZigZagPivotPrices); + SpecifiedClean(mZigZagPivotIsPeaks); + SpecifiedClean(mZigZagPivotIndexes); + + // + // Looping Through ZigZag Buffers ... + XOHCL iBar; + bool has = false; + double iZigZag = 0; + bool isIZigZagPeak = false; + int count = ArraySize(mZigZagBuffer); + for (int i = 0; i < count; i++) + { + // + // Reading ZigZag Value ... + iZigZag = mZigZagBuffer[i]; + + // + // Validate ZigZag Values ... + if (!NotEmptyZero(iZigZag)) + { + continue; + } + + // + // Check ZigZag Value Is Peak or Vale ... + + // + // Initialize iBar ... + has = iBar.Init( + _Symbol, + _Period, + i // + ); + + // + // Validate Bar and also Exclude Most Recent Swing ... + if (!has || iBar.Index() == 0) + { + // + iBar.Clean(); + continue; + } + + // + isIZigZagPeak = iZigZag == iBar.high; + + // + // Filling Buffers ... + Add( + iBar.time, + mZigZagPivotTimes // + ); + Add( + iZigZag, + mZigZagPivotPrices // + ); + Add( + isIZigZagPeak, + mZigZagPivotIsPeaks // + ); + Add( + (double)iBar.Index(), + mZigZagPivotIndexes // + ); + + // + // Cleanup Resources ... + iBar.Clean(); + } + + // + return result; +} + +// +int ReadingZigZagPivots( + int barIndex = 0, + int requiredPivots = 15, + int maxAllowedLoopback = 1500 // +) +{ + // + int result = 0; + + // + // Cleanup Resources ... + SpecifiedClean(mZigZagPivotTimes); + SpecifiedClean(mZigZagPivotPrices); + SpecifiedClean(mZigZagPivotIsPeaks); + SpecifiedClean(mZigZagPivotIndexes); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredPivots = NormalizeInt(requiredPivots, 2); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 100); + + // + XOHCL iBar; + bool has = false; + double iZigZag = 0; + bool isPeak = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + int maxAllowed = barIndex + maxAllowedLoopback; + while (idx < maxAllowed && + ArraySize(mZigZagPivotPrices) < requiredPivots) + { + // + idx++; + + // + // Initializing Bar ... + has = iBar.Init( + _Symbol, + _Period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading ZigZag Value ... + if (CopyBuffer(mZigZagHandler, MAIN_LINE, idx, 1, tmpZigZagBuffer) < 1) + { + // + iBar.Clean(); + continue; + } + + // + // Read ZigZag Value and Validate it ... + iZigZag = tmpZigZagBuffer[0]; + has = NotEmptyZero(iZigZag); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + continue; + } + + // + isPeak = iZigZag == iBar.high; + + // + // Validate ZigZag Value for Ignore Zero ... + if (iBar.Index() == barIndex) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + continue; + } + + // + // Filling Pivots ... + + // + Add( + iZigZag, + mZigZagPivotPrices // + ); + + // + Add( + isPeak, + mZigZagPivotIsPeaks // + ); + + // + Add( + iBar.time, + mZigZagPivotTimes // + ); + + // + Add( + (double)iBar.Index(), + mZigZagPivotIndexes // + ); + + // + // Cleanup Resources ... + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Can Break Loop ... + has = idx >= maxAllowed || + ArraySize(mZigZagPivotPrices) == requiredPivots; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + SpecifiedClean(tmpZigZagBuffer); + + // + result = ArraySize(mZigZagPivotPrices); + + // + return result; +} + +// +void ProcessZigZagsPeaksAndVales() +{ + // + // Here we Parse ZigZag Values to Detect Peak or Vale ... + + // + int count = 0; + bool has = false; + + // + // Extract mZigZag Peaks and Vales ... + SpecifiedClean(mZigZagPeaks); + SpecifiedClean(mZigZagVales); + SpecifiedClean(mZigZagPeakTimes); + SpecifiedClean(mZigZagValeTimes); + SpecifiedClean(mZigZagPeakIndexes); + SpecifiedClean(mZigZagValeIndexes); + count = ArraySize(mZigZagPivotPrices); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + double iZigZag = 0; + double iZigZagIDX = -1; + bool isIZigZagPeak = false; + datetime iZigZagTime = NULL; + for (int i = 0; i < count; i++) + { + // + // Reading Required Values ... + iZigZag = mZigZagPivotPrices[i]; + iZigZagTime = mZigZagPivotTimes[i]; + iZigZagIDX = mZigZagPivotIndexes[i]; + isIZigZagPeak = mZigZagPivotIsPeaks[i]; + + // + if (isIZigZagPeak) + { + // + Add( + iZigZag, + mZigZagPeaks // + ); + + // + Add( + iZigZagTime, + mZigZagPeakTimes // + ); + + // + Add( + iZigZagIDX, + mZigZagPeakIndexes // + ); + } + else + { + // + Add( + iZigZag, + mZigZagVales // + ); + + // + Add( + iZigZagTime, + mZigZagValeTimes // + ); + + // + Add( + iZigZagIDX, + mZigZagValeIndexes // + ); + } + } +} + +// +void ProcessZigZagsSupportsAnsResistances() +{ + // + int count = 0; + bool has = false; + double iValue = EMPTY_VALUE; + double tmpValue = EMPTY_VALUE; + + // + // Support ... + // Supports Calculated based on Vales ... + + // + tmpValue = EMPTY_VALUE; + mMinorSupport = EMPTY_VALUE; + mMajorSupport = EMPTY_VALUE; + count = ArraySize(mZigZagVales); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + // Reading Indexed Value ... + iValue = mZigZagVales[i]; + + // + // Check Can Change Major Support ... + has = !NotEmpty(mMajorSupport) || + mMajorSupport > iValue; + if (has) + { + // + tmpValue = mMajorSupport; + mMajorSupport = iValue; + } + else + { + // + // Check Minor Support ... + has = !NotEmpty(tmpValue) || + tmpValue > iValue; + if (has) + { + tmpValue = iValue; + } + } + } + + // + has = NotEmpty(tmpValue); + if (has) + { + mMinorSupport = tmpValue; + } + } + + // + // Resistance ... + // Resistances Calculated based on Peaks ... + + // + tmpValue = EMPTY_VALUE; + mMinorResistance = EMPTY_VALUE; + mMajorResistance = EMPTY_VALUE; + count = ArraySize(mZigZagPeaks); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + // Reading Indexed Value ... + iValue = mZigZagPeaks[i]; + + // + // Check Can Change Major Resistance ... + has = !NotEmpty(mMajorResistance) || + mMajorResistance < iValue; + if (has) + { + // + tmpValue = mMajorResistance; + mMajorResistance = iValue; + } + elsetmp + { + // + // Check Minor Resistance ... + has = !NotEmpty(tmpValue) || + tmpValue < iValue; + if (has) + { + tmpValue = iValue; + } + } + } + + // + has = NotEmpty(tmpValue); + if (has) + { + mMinorResistance = tmpValue; + } + } +} + +// +bool CalculateZigZagLinearRegressionParameters() +{ + // + bool result = false; + mUpperTrendDir = X_DIRECTION_NONE; + mLowerTrendDir = X_DIRECTION_NONE; + + // + // Peaks ... + CalculateSlopeAndIntercept( + mPeakSlope, + mPeakIntercept, + mZigZagPeakIndexes, + mZigZagPeaks // + ); + + // + // Vales ... + CalculateSlopeAndIntercept( + mValeSlope, + mValeIntercept, + mZigZagValeIndexes, + mZigZagVales // + ); + + // + result = + (NotEmpty(mPeakSlope) && + NotEmpty(mPeakIntercept)) || + (NotEmpty(mValeSlope) && + NotEmpty(mValeIntercept)); + if (!result) + { + return result; + } + + // + // Detect Oldest and Youngest Time of Pivots ... + + // + int idx = -1; + bool has = false; + + // + // Oldest ... + has = FindOldestIndex( + idx, + mZigZagPivotTimes // + ); + if (has) + { + mFromTime = mZigZagPivotTimes[idx]; + } + + // + // Youngest ... + has = FindYoungesttIndex( + idx, + mZigZagPivotTimes // + ); + if (has) + { + mToTime = mZigZagPivotTimes[idx]; + } + + // + // Validate Extracted Times ... + result = + IsSpecifiedValid(mToTime) && + IsSpecifiedValid(mFromTime); + if (!result) + { + return result; + } + + // + // Detect Extracted Times Bar Indexes ... + + // + int mToIDX = iBarShift( + _Symbol, + _Period, + mToTime // + ); + int mFromIDX = iBarShift( + _Symbol, + _Period, + mFromTime // + ); + + // + // Validate Detected Bar Indexes ... + result = + IsValidIndex(mToIDX) && + IsValidIndex(mFromIDX); + if (!result) + { + return result; + } + + // + // Calculate Predictions ... + + // + // Peak ... + mPeakTo = PredictValue( + mPeakSlope, + mPeakIntercept, + mToIDX // + ); + mPeakFrom = PredictValue( + mPeakSlope, + mPeakIntercept, + mFromIDX // + ); + + // + // Vale ... + mValeTo = PredictValue( + mValeSlope, + mValeIntercept, + mToIDX // + ); + mValeFrom = PredictValue( + mValeSlope, + mValeIntercept, + mFromIDX // + ); + + // + mUpperTrendDir = + mPeakFrom < mPeakTo + ? X_DIRECTION_BULLISH + : mPeakFrom > mPeakTo + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + mLowerTrendDir = + mValeFrom < mValeTo + ? X_DIRECTION_BULLISH + : mValeFrom > mValeTo + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + // Prepare Support and Resistance Boxes ... + + // + // Support ... + + // + mSupportBox.Clean(); + has = NotEmptyZero(mMinorSupport) && + NotEmptyZero(mMajorSupport); + if (has) + { + // + mSupportBox.to = mToTime; + mSupportBox.from = mFromTime; + mSupportBox.symbol = _Symbol; + mSupportBox.period = _Period; + mSupportBox.type = "Support"; + mSupportBox.upper = mMinorSupport; + mSupportBox.lower = mMajorSupport; + mSupportBox.dir = X_DIRECTION_BULLISH; + } + + // + // Resistance ... + + // + mResistanceBox.Clean(); + has = NotEmptyZero(mMinorResistance) && + NotEmptyZero(mMajorResistance); + if (has) + { + // + mResistanceBox.to = mToTime; + mResistanceBox.from = mFromTime; + mResistanceBox.symbol = _Symbol; + mResistanceBox.period = _Period; + mResistanceBox.type = "Resistance"; + mResistanceBox.upper = mMajorResistance; + mResistanceBox.lower = mMinorResistance; + mResistanceBox.dir = X_DIRECTION_BEARISH; + } + + // + result = + mSupportBox.IsValid() || + mResistanceBox.IsValid(); + + // + return result; +} + +// +void DrawAnalysis() +{ + // + bool isCreated = false; + + // + // Peak ... + + // + // Cleanup Upper Object ... + if (mUpperTrend != NULL) + { + // + mUpperTrend.Delete(); + mUpperTrend.Detach(); + delete mUpperTrend; + ZeroMemory(mUpperTrend); + } + + // + mUpperTrend = new CChartObjectTrend(); + isCreated = mUpperTrend.Create( + ChartID(), + "UpperTrend", + 0, + mFromTime, + mPeakFrom, + mToTime, + mPeakTo // + ); + if (isCreated) + { + // + // Apply Styles ... + + // + color upperColor = + IsSpecifiedBullish(mUpperTrendDir) + ? clrAqua + : IsSpecifiedBearish(mUpperTrendDir) + ? clrMagenta + : clrGray; // Neutural ... + + // + mUpperTrend.Width(2); + mUpperTrend.RayRight(true); + mUpperTrend.Color(upperColor); + } + + // + // Vale ... + + // + // Cleanup Lower Object ... + if (mLowerTrend != NULL) + { + // + mLowerTrend.Delete(); + mLowerTrend.Detach(); + delete mLowerTrend; + ZeroMemory(mLowerTrend); + } + + // + mLowerTrend = new CChartObjectTrend(); + isCreated = mLowerTrend.Create( + ChartID(), + "LowerTrend", + 0, + mFromTime, + mValeFrom, + mToTime, + mValeTo // + ); + if (isCreated) + { + // + // Apply Styles ... + + // + color lowerColor = + IsSpecifiedBullish(mLowerTrendDir) + ? clrAqua + : IsSpecifiedBearish(mLowerTrendDir) + ? clrMagenta + : clrGray; // Neutural ... + + // + mLowerTrend.Width(2); + mLowerTrend.RayRight(true); + mLowerTrend.Color(lowerColor); + } + + // + // Support ... + + // + // Cleanup Support Object ... + if (mSupportObj != NULL) + { + // + mSupportObj.Delete(); + mSupportObj.Detach(); + delete mSupportObj; + ZeroMemory(mSupportObj); + } + + // + isCreated = mSupportBox.IsValid(); + if (isCreated) + { + // + datetime to = TimeCurrent(); + mSupportObj = new XCBoxObject(); + isCreated = mSupportObj.Create( + ChartID(), + 0, + "Support", + mSupportBox.upper, + mSupportBox.lower, + mSupportBox.from, + to // + ); + if (isCreated) + { + // + // Apply Style ... + mSupportObj.BoxWidth(2); + mSupportObj.BoxColor(clrAqua); + } + } + + // + // Resistance ... + + // + // Cleanup Resistance Object ... + if (mResistanceObj != NULL) + { + // + mResistanceObj.Delete(); + mResistanceObj.Detach(); + delete mResistanceObj; + ZeroMemory(mResistanceObj); + } + + // + isCreated = mResistanceBox.IsValid(); + if (isCreated) + { + // + datetime to = TimeCurrent(); + mResistanceObj = new XCBoxObject(); + isCreated = mResistanceObj.Create( + ChartID(), + 0, + "Resistance", + mResistanceBox.upper, + mResistanceBox.lower, + mResistanceBox.from, + to // + ); + if (isCreated) + { + // + // Apply Style ... + mResistanceObj.BoxWidth(2); + mResistanceObj.BoxColor(clrMagenta); + } + } +} + +// +int FindOldestIndex( + int &index, + datetime ×[] // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + if (!HasChild(times)) + { + return result; + } + + // + bool has = false; + datetime tmpTime = NULL; + for (int i = 0; i < ArraySize(times); i++) + { + // + has = + !IsSpecifiedValid(tmpTime) + ? true + : tmpTime > times[i]; + if (has) + { + // + index = i; + tmpTime = times[i]; + } + } + + // + // Validate result ... + result = + IsValidIndex(index) && + IsSpecifiedValid(tmpTime); + + // + return result; +} + +// +int FindYoungesttIndex( + int &index, + datetime ×[] // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + if (!HasChild(times)) + { + return result; + } + + // + bool has = false; + datetime tmpTime = NULL; + for (int i = 0; i < ArraySize(times); i++) + { + // + has = + !IsSpecifiedValid(tmpTime) + ? true + : tmpTime < times[i]; + if (has) + { + // + index = i; + tmpTime = times[i]; + } + } + + // + // Validate result ... + result = + IsValidIndex(index) && + IsSpecifiedValid(tmpTime); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZag.ex5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZag.ex5 new file mode 100644 index 0000000..8fe28be Binary files /dev/null and b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZag.ex5 differ diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZag.mq5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZag.mq5 new file mode 100644 index 0000000..3863bd7 Binary files /dev/null and b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZag.mq5 differ diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZagColor.ex5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZagColor.ex5 new file mode 100644 index 0000000..592b07f Binary files /dev/null and b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZagColor.ex5 differ diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZagColor.mq5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZagColor.mq5 new file mode 100644 index 0000000..ed3448a --- /dev/null +++ b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/ZigZagColor.mq5 @@ -0,0 +1,288 @@ +//+------------------------------------------------------------------+ +//| ZigzagColor.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +//--- indicator settings +#property indicator_chart_window +#property indicator_buffers 5 +#property indicator_plots 1 +#property indicator_type1 DRAW_COLOR_ZIGZAG +#property indicator_width1 3 +#property indicator_color1 clrAqua, clrMagenta +//--- input parameters +input int InpDepth =12; // Depth +input int InpDeviation=5; // Deviation +input int InpBackstep =3; // Back Step +//--- indicator buffers +double ZigzagPeakBuffer[]; +double ZigzagBottomBuffer[]; +double HighMapBuffer[]; +double LowMapBuffer[]; +double ColorBuffer[]; + +int ExtRecalc=3; // recounting's depth + +enum EnSearchMode + { + Extremum=0, // searching for the first extremum + Peak=1, // searching for the next ZigZag peak + Bottom=-1 // searching for the next ZigZag bottom + }; +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- indicator buffers mapping + SetIndexBuffer(0,ZigzagPeakBuffer,INDICATOR_DATA); + SetIndexBuffer(1,ZigzagBottomBuffer,INDICATOR_DATA); + SetIndexBuffer(2,ColorBuffer,INDICATOR_COLOR_INDEX); + SetIndexBuffer(3,HighMapBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(4,LowMapBuffer,INDICATOR_CALCULATIONS); +//--- set accuracy + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//--- name for DataWindow and indicator subwindow label + string short_name=StringFormat("ZigZagColor(%d,%d,%d)",InpDepth,InpDeviation,InpBackstep); + IndicatorSetString(INDICATOR_SHORTNAME,short_name); + PlotIndexSetString(0,PLOT_LABEL,short_name); +//--- set an empty value + PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); + } +//+------------------------------------------------------------------+ +//| ZigZag calculation | +//+------------------------------------------------------------------+ +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(rates_total<100) + return(0); +//--- + int i,start=0; + int extreme_counter=0,extreme_search=Extremum; + int shift,back=0,last_high_pos=0,last_low_pos=0; + double val=0,res=0; + double cur_low=0,cur_high=0,last_high=0,last_low=0; +//--- initializing + if(prev_calculated==0) + { + ArrayInitialize(ZigzagPeakBuffer,0.0); + ArrayInitialize(ZigzagBottomBuffer,0.0); + ArrayInitialize(HighMapBuffer,0.0); + ArrayInitialize(LowMapBuffer,0.0); + //--- start calculation from bar number InpDepth + start=InpDepth-1; + } +//--- ZigZag was already calculated before + if(prev_calculated>0) + { + i=rates_total-1; + //--- searching for the third extremum from the last uncompleted bar + while(extreme_counterrates_total -100) + { + res=(ZigzagPeakBuffer[i]+ZigzagBottomBuffer[i]); + //--- + if(res!=0) + extreme_counter++; + i--; + } + i++; + start=i; + //--- what type of exremum we search for + if(LowMapBuffer[i]!=0) + { + cur_low=LowMapBuffer[i]; + extreme_search=Peak; + } + else + { + cur_high=HighMapBuffer[i]; + extreme_search=Bottom; + } + //--- clear indicator values + for(i=start+1; i(InpDeviation*_Point)) + val=0.0; + else + { + for(back=InpBackstep; back>=1; back--) + { + res=LowMapBuffer[shift-back]; + //--- + if((res!=0) && (res>val)) + LowMapBuffer[shift-back]=0.0; + } + } + } + if(low[shift]==val) + LowMapBuffer[shift]=val; + else + LowMapBuffer[shift]=0.0; + //--- high + val=Highest(high,InpDepth,shift); + if(val==last_high) + val=0.0; + else + { + last_high=val; + if((val-high[shift])>(InpDeviation*_Point)) + val=0.0; + else + { + for(back=InpBackstep; back>=1; back--) + { + res=HighMapBuffer[shift-back]; + //--- + if((res!=0) && (reslast_high && + LowMapBuffer[shift]==0.0) + { + ZigzagPeakBuffer[last_high_pos]=0.0; + last_high_pos=shift; + last_high=HighMapBuffer[shift]; + ZigzagPeakBuffer[shift]=last_high; + ColorBuffer[shift]=0; + } + if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0) + { + last_low=LowMapBuffer[shift]; + last_low_pos=shift; + ZigzagBottomBuffer[shift]=last_low; + ColorBuffer[shift]=1; + extreme_search=Peak; + } + break; + default: + return(rates_total); + } + } + +//--- return value of prev_calculated for next call + return(rates_total); + } +//+------------------------------------------------------------------+ +//| Get highest value for range | +//+------------------------------------------------------------------+ +double Highest(const double&array[],int count,int start) + { + double res=array[start]; +//--- + for(int i=start-1; i>start-count && i>=0; i--) + if(resstart-count && i>=0; i--) + if(res>array[i]) + res=array[i]; +//--- + return(res); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/x-saherelm.xzg.mq5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/x-saherelm.xzg.mq5 new file mode 100644 index 0000000..0492a50 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/x-saherelm.xzg.mq5 @@ -0,0 +1,1111 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XZG +// Description: ZigZag Implementation ... +// +// +// 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 XZG Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +#define ShortName "XZG" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +// Inputs ... + +// +input group "Calculation"; +input int depth = 12; // Depth +input int deviation = 5; // Deviation +input int backStep = 3; // Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // Low Detect Mode + +// +// Presentation ... +input group "Presentation"; +input bool showPeaks = true; // Show Peaks +input bool showVales = true; // Show Vales +input bool showZigZag = true; // Show ZigZag +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 7 +#property indicator_plots 3 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 0 +#define zigzagBufferPlotIndex 0 +double zigzagBuffer[]; + +// +#property indicator_label1 "XZG" +#property indicator_type1 DRAW_SECTION +#property indicator_color1 clrYellow +#property indicator_width1 2 + +// +// Peaks ... + +// +#define peakBufferIndex 1 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 3 + +// +// Vales ... + +// +#define valeBufferIndex 2 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 2 + +// +#define highsBufferIndex mLastBufferIndex + 1 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 2 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 3 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 4 +double lowsTimeBuffer[]; + +// +// Variables, Properties and etc ... + +// +int mRecalc = 3; // Number of last extremes for recalculation + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; + +// +double lastZigZagPeak = 0; +datetime lastZigZagPeakTime = NULL; + +// +double lastZigZagVale = 0; +datetime lastZigZagValeTime = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + 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(); + + // + // Initial Requirements ... + + // + // 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // Checking PrevCalculated ... + if (prev_calculated == rates_total) + { + return rates_total; + } + + // + // Calculating Limit ... + limit = prev_calculated == 0 + ? rates_total - 1 + : rates_total - prev_calculated; + if (limit <= 0) + { + limit = rates_total - 1; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total - 1 && !IsStopped(); i++) + { + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales( + 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 = + // + // Inputs ... + depth > 0 && + deviation > 0 && + backStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // PEAK ... + + // + ENUM_DRAW_TYPE peaksDrawType = showPeaks ? DRAW_ARROW : DRAW_NONE; + + // + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPeaks); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, peaksDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ENUM_DRAW_TYPE valesDrawType = showVales ? DRAW_ARROW : DRAW_NONE; + + // + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showVales); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, valesDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // Data Buffers ... + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * 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 ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = depth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < mRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, depth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, depth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +/** + * Calculate Peaks and Vales ... + * + * @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 CalculatePeaksAndVales( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iZigZagValue = zigzagBuffer[barIndex]; + + // + // Peak ... + double iHighValue = highsBuffer[barIndex]; + double iHighTimeDouble = highsTimeBuffer[barIndex]; + datetime iHighTime = (datetime)((int)iHighTimeDouble); + if (iHighValue != 0 && iHighValue != EMPTY_VALUE && iZigZagValue == iHighValue) + { + // + peakBuffer[barIndex] = iHighValue; + + // + lastZigZagPeak = iHighValue; + lastZigZagPeakTime = iHighTime; + } + else + { + // + double iValue = emptyValue; + if ( + lastZigZagPeak != emptyValue && + lastZigZagPeak != EMPTY_VALUE && + IsSpecifiedValid(lastZigZagPeakTime)) + { + iValue = lastZigZagPeak; + } + + // + peakBuffer[barIndex] = iValue; + } + + // + // Vale ... + double iLowValue = lowsBuffer[barIndex]; + double iLowTimeDouble = lowsTimeBuffer[barIndex]; + datetime iLowTime = (datetime)((int)iLowTimeDouble); + if (iLowValue != 0 && iLowValue != EMPTY_VALUE && iZigZagValue == iLowValue) + { + // + valeBuffer[barIndex] = iLowValue; + + // + lastZigZagVale = iLowValue; + lastZigZagValeTime = iLowTime; + } + else + { + // + double iValue = emptyValue; + if ( + lastZigZagVale != emptyValue && + lastZigZagVale != EMPTY_VALUE && + IsSpecifiedValid(lastZigZagValeTime)) + { + iValue = lastZigZagVale; + } + + // + valeBuffer[barIndex] = iValue; + } +} + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} diff --git a/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/x-zigzag.analyser.ea.mq5 b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/x-zigzag.analyser.ea.mq5 new file mode 100644 index 0000000..c66d88e --- /dev/null +++ b/BKPS/14041018/Documents/BKP/ZigZagLinearRegression/x-zigzag.analyser.ea.mq5 @@ -0,0 +1,383 @@ +//+------------------------------------------------------------------+ +//| ZigZag Analyzer.mq5| +//| Copyright 2025, MetaQuotes Ltd.| +//| https://www.mql5.com/en/users/lynnchris| +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, MetaQuotes Ltd." +#property link "https://www.mql5.com/en/users/lynnchris" +#property version "1.0" +#property strict + +// +#include "../Libraries/x-saherelm.common.lib.mq5" + +// Input parameters +input ENUM_TIMEFRAMES InpTimeFrame = PERIOD_CURRENT; // Timeframe to analyze +input int ZZ_Depth = 12; // ZigZag depth +input int ZZ_Deviation = 5; // ZigZag deviation +input int ZZ_Backstep = 3; // ZigZag backstep +input int LookBackBars = 500; // Bars to search for pivots +input int ExtendFutureBars = 100; // Bars to extend trendlines into the future + +// Global indicator handle for ZigZag +int zzHandle; + +// Arrays for ZigZag data and pivot storage +double zzBuffer[]; +bool pivotIsPeak[]; +double pivotPrices[]; +datetime pivotTimes[]; + +// Variable to detect new bars +datetime lastBarTime = 0; + +//+------------------------------------------------------------------+ +//| Initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + zzHandle = iCustom( + _Symbol, + InpTimeFrame, + "x-saherelm.xzg", + "", + ZZ_Depth, + ZZ_Deviation, + ZZ_Backstep, + X_PRICE_HIGH, + X_PRICE_LOW, + "", + false, + false, + true, + 159, + 159 // + ); + if (zzHandle == INVALID_HANDLE) + { + Print("Error creating ZigZag handle"); + return (INIT_FAILED); + } + return (INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + ObjectDelete(0, "Downtrend_HighLine"); + ObjectDelete(0, "Downtrend_LowLine"); + ObjectDelete(0, "Major_Resistance"); + ObjectDelete(0, "Major_Support"); + ObjectDelete(0, "Minor_Resistance"); + ObjectDelete(0, "Minor_Support"); + IndicatorRelease(zzHandle); +} + +//+------------------------------------------------------------------+ +//| Tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + datetime currentBarTime = iTime(_Symbol, InpTimeFrame, 0); + if (currentBarTime == lastBarTime) + return; + lastBarTime = currentBarTime; + + // Remove previous objects + ObjectDelete(0, "Downtrend_HighLine"); + ObjectDelete(0, "Downtrend_LowLine"); + ObjectDelete(0, "Major_Resistance"); + ObjectDelete(0, "Major_Support"); + ObjectDelete(0, "Minor_Resistance"); + ObjectDelete(0, "Minor_Support"); + + if (CopyBuffer(zzHandle, 0, 0, LookBackBars, zzBuffer) <= 0) + { + Print("Failed to copy ZigZag data"); + return; + } + ArraySetAsSeries(zzBuffer, true); + + DrawZigZagTrendlines(); + DrawSupportResistance(); +} + +//+------------------------------------------------------------------+ +//| Draw ZigZag-based Trendlines | +//+------------------------------------------------------------------+ +void DrawZigZagTrendlines() +{ + double highPrices[10], lowPrices[10]; + datetime highTimes[10], lowTimes[10]; + int highCount = 0, lowCount = 0; + + // Extract swing points from the ZigZag buffer + for (int i = 0; i < LookBackBars - 1; i++) + { + if (zzBuffer[i] != 0) + { + if (iHigh(_Symbol, InpTimeFrame, i) == zzBuffer[i] && highCount < 10) + { + highPrices[highCount] = zzBuffer[i]; + highTimes[highCount] = iTime(_Symbol, InpTimeFrame, i); + highCount++; + } + else if (iLow(_Symbol, InpTimeFrame, i) == zzBuffer[i] && lowCount < 10) + { + lowPrices[lowCount] = zzBuffer[i]; + lowTimes[lowCount] = iTime(_Symbol, InpTimeFrame, i); + lowCount++; + } + } + } + + // Exclude the most recent swing if possible + int usedHighCount = (highCount >= 4) ? highCount - 1 : highCount; + int usedLowCount = (lowCount >= 4) ? lowCount - 1 : lowCount; + + double mHigh = 0, bHigh = 0, mLow = 0, bLow = 0; + bool validHigh = false, validLow = false; + + // Regression for highs + if (usedHighCount >= 3) + { + double sumT = 0, sumP = 0, sumTP = 0, sumT2 = 0; + for (int i = 0; i < usedHighCount; i++) + { + double t = (double)highTimes[i]; + double p = highPrices[i]; + sumT += t; + sumP += p; + sumTP += t * p; + sumT2 += t * t; + } + int N = usedHighCount; + double denominator = N * sumT2 - sumT * sumT; + if (denominator != 0) + { + mHigh = (N * sumTP - sumT * sumP) / denominator; + bHigh = (sumP - mHigh * sumT) / N; + } + else + bHigh = sumP / N; + validHigh = true; + } + + // Regression for lows + if (usedLowCount >= 3) + { + double sumT = 0, sumP = 0, sumTP = 0, sumT2 = 0; + for (int i = 0; i < usedLowCount; i++) + { + double t = (double)lowTimes[i]; + double p = lowPrices[i]; + sumT += t; + sumP += p; + sumTP += t * p; + sumT2 += t * t; + } + int N = usedLowCount; + double denominator = N * sumT2 - sumT * sumT; + if (denominator != 0) + { + mLow = (N * sumTP - sumT * sumP) / denominator; + bLow = (sumP - mLow * sumT) / N; + } + else + bLow = sumP / N; + validLow = true; + } + + // Define time limits for trendlines + datetime pastTime = iTime(_Symbol, InpTimeFrame, LookBackBars - 1); + datetime futureTime = lastBarTime + ExtendFutureBars * PeriodSeconds(); + + // Draw trendlines if both regressions are valid + if (validHigh && validLow) + { + // When slopes have the same sign, use average slope + if (mHigh * mLow > 0) + { + double mParallel = (mHigh + mLow) / 2.0; + double bHighParallel = highPrices[0] - mParallel * (double)highTimes[0]; + double bLowParallel = lowPrices[0] - mParallel * (double)lowTimes[0]; + + datetime highStartTime = pastTime; + double highStartPrice = mParallel * (double)highStartTime + bHighParallel; + double highEndPrice = mParallel * (double)futureTime + bHighParallel; + if (!ObjectCreate(0, "Downtrend_HighLine", OBJ_TREND, 0, highStartTime, highStartPrice, futureTime, highEndPrice)) + Print("Failed to create High Trendline"); + else + { + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_COLOR, clrRed); + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_RAY_LEFT, true); + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_RAY_RIGHT, true); + } + + datetime lowStartTime = pastTime; + double lowStartPrice = mParallel * (double)lowStartTime + bLowParallel; + double lowEndPrice = mParallel * (double)futureTime + bLowParallel; + if (!ObjectCreate(0, "Downtrend_LowLine", OBJ_TREND, 0, lowStartTime, lowStartPrice, futureTime, lowEndPrice)) + Print("Failed to create Low Trendline"); + else + { + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_COLOR, clrGreen); + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_RAY_LEFT, true); + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_RAY_RIGHT, true); + } + } + else + { + datetime highStartTime = pastTime; + double highStartPrice = mHigh * (double)highStartTime + bHigh; + double highEndPrice = mHigh * (double)futureTime + bHigh; + if (!ObjectCreate(0, "Downtrend_HighLine", OBJ_TREND, 0, highStartTime, highStartPrice, futureTime, highEndPrice)) + Print("Failed to create High Trendline"); + else + { + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_COLOR, clrRed); + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_RAY_LEFT, true); + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_RAY_RIGHT, true); + } + + datetime lowStartTime = pastTime; + double lowStartPrice = mLow * (double)lowStartTime + bLow; + double lowEndPrice = mLow * (double)futureTime + bLow; + if (!ObjectCreate(0, "Downtrend_LowLine", OBJ_TREND, 0, lowStartTime, lowStartPrice, futureTime, lowEndPrice)) + Print("Failed to create Low Trendline"); + else + { + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_COLOR, clrGreen); + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_RAY_LEFT, true); + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_RAY_RIGHT, true); + } + } + } + else + { + if (validHigh) + { + datetime highStartTime = pastTime; + double highStartPrice = mHigh * (double)highStartTime + bHigh; + double highEndPrice = mHigh * (double)futureTime + bHigh; + if (!ObjectCreate(0, "Downtrend_HighLine", OBJ_TREND, 0, highStartTime, highStartPrice, futureTime, highEndPrice)) + Print("Failed to create High Trendline"); + else + { + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_COLOR, clrRed); + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_RAY_LEFT, true); + ObjectSetInteger(0, "Downtrend_HighLine", OBJPROP_RAY_RIGHT, true); + } + } + if (validLow) + { + datetime lowStartTime = pastTime; + double lowStartPrice = mLow * (double)lowStartTime + bLow; + double lowEndPrice = mLow * (double)futureTime + bLow; + if (!ObjectCreate(0, "Downtrend_LowLine", OBJ_TREND, 0, lowStartTime, lowStartPrice, futureTime, lowEndPrice)) + Print("Failed to create Low Trendline"); + else + { + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_COLOR, clrGreen); + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_RAY_LEFT, true); + ObjectSetInteger(0, "Downtrend_LowLine", OBJPROP_RAY_RIGHT, true); + } + } + } +} + +//+------------------------------------------------------------------+ +//| Draw Support and Resistance Levels | +//+------------------------------------------------------------------+ +void DrawSupportResistance() +{ + double confirmedHighs[10], confirmedLows[10]; + int confHighCount = 0, confLowCount = 0; + + for (int i = 0; i < LookBackBars - 1; i++) + { + if (zzBuffer[i] != 0) + { + if (iHigh(_Symbol, InpTimeFrame, i) == zzBuffer[i] && confHighCount < 10) + { + confirmedHighs[confHighCount] = zzBuffer[i]; + confHighCount++; + } + else if (iLow(_Symbol, InpTimeFrame, i) == zzBuffer[i] && confLowCount < 10) + { + confirmedLows[confLowCount] = zzBuffer[i]; + confLowCount++; + } + } + } + + int usedHighCount = (confHighCount >= 4) ? confHighCount - 1 : confHighCount; + int usedLowCount = (confLowCount >= 4) ? confLowCount - 1 : confLowCount; + + double majorResistance = -1e9, majorSupport = 1e9; + double minorResistance = -1e9, minorSupport = 1e9; + double tempHigh = -1e9, tempLow = -1e9; + for (int i = 0; i < usedHighCount; i++) + { + if (confirmedHighs[i] > majorResistance) + { + tempHigh = majorResistance; + majorResistance = confirmedHighs[i]; + } + else if (confirmedHighs[i] > tempHigh) + { + tempHigh = confirmedHighs[i]; + } + } + if (tempHigh > -1e9) + minorResistance = tempHigh; + for (int i = 0; i < usedLowCount; i++) + { + if (confirmedLows[i] < majorSupport) + { + tempLow = majorSupport; + majorSupport = confirmedLows[i]; + } + else if (confirmedLows[i] < tempLow) + { + tempLow = confirmedLows[i]; + } + } + if (tempLow < 1e9) + minorSupport = tempLow; + + if (usedHighCount > 0) + { + if (!ObjectCreate(0, "Major_Resistance", OBJ_HLINE, 0, 0, majorResistance)) + Print("Failed to create Major Resistance"); + else + ObjectSetInteger(0, "Major_Resistance", OBJPROP_COLOR, clrMagenta); + + if (minorResistance > -1e9 && minorResistance < majorResistance) + { + if (!ObjectCreate(0, "Minor_Resistance", OBJ_HLINE, 0, 0, minorResistance)) + Print("Failed to create Minor Resistance"); + else + ObjectSetInteger(0, "Minor_Resistance", OBJPROP_COLOR, clrFuchsia); + } + } + if (usedLowCount > 0) + { + if (!ObjectCreate(0, "Major_Support", OBJ_HLINE, 0, 0, majorSupport)) + Print("Failed to create Major Support"); + else + ObjectSetInteger(0, "Major_Support", OBJPROP_COLOR, clrAqua); + + if (minorSupport < 1e9 && minorSupport > majorSupport) + { + if (!ObjectCreate(0, "Minor_Support", OBJ_HLINE, 0, 0, minorSupport)) + Print("Failed to create Minor Support"); + else + ObjectSetInteger(0, "Minor_Support", OBJPROP_COLOR, clrBlue); + } + } +} +//+------------------------------------------------------------------+ diff --git a/BKPS/14041018/Documents/BKP/backtester.temp.mq5 b/BKPS/14041018/Documents/BKP/backtester.temp.mq5 new file mode 100644 index 0000000..e01c1c0 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/signaller.xfima.drawing.tmp.mq5 b/BKPS/14041018/Documents/BKP/signaller.xfima.drawing.tmp.mq5 new file mode 100644 index 0000000..d63e9a0 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/signaller.xfima.drawing.tmp.mq5 @@ -0,0 +1,208 @@ + +// +// Draw Market Analysis ... +// has = iStructure.pvAnalysis.IsValid(); +// if (has) +// { +// // +// XBoxZone iBox; +// XCBoxObject *iBoxObj; + +// +// poiDrawer.RemoveDraws(); + +// // +// has = iStructure.pvAnalysis.HasSupportBox(iBox); +// if (has) +// { +// // +// iBox.to = iBar.time; +// poiDrawer.DrawBox( +// iBox, +// iBoxObj, +// true, +// iBox.type // +// ); +// } + +// // +// ZeroMemory(iBoxObj); +// has = iStructure.pvAnalysis.HasResistanceBox(iBox); +// if (has) +// { +// // +// iBox.to = iBar.time; +// poiDrawer.DrawBox( +// iBox, +// iBoxObj, +// true, +// iBox.type // +// ); +// } +// } + +// // +// // Draw Zones ... +// has = HasChild(iStructure.supports); +// if (has) { +// // +// CArrayObj *iSupportObjs; +// poiDrawer.DrawBoxes( +// iStructure.supports, +// iSupportObjs, +// true // +// ); +// } + +// // +// has = HasChild(iStructure.resistances); +// if (has) { +// // +// CArrayObj *iResistanceObjs; +// poiDrawer.DrawBoxes( +// iStructure.resistances, +// iResistanceObjs, +// true // +// ); +// } + +// +// Detecte Fibo Section Changes ... + +// // +// has = fimaHelper.IsFiboSectionChanged(iDir, iBar.Index()); +// has = has && +// IsXBullish(iDir) && +// fimaHelper.IsValeOverLast(iBar.Index()); + +// // +// has = fimaHelper.IsFiboSectionChanged(iDir, iBar.Index()); +// has = has && +// IsXBearish(iDir) && +// fimaHelper.IsPeakUnderLast(iBar.Index()); + +// // +// has = fimaHelper.HasFiboPush(iDir, iBar.Index(), 5); + +// // +// XBoxZone fimaZones[]; +// int fimaZonesCount = fimaHelper.DetectXFIMAZones( +// fimaZones, +// iBar.Index(), +// true, // Only Valid Zones ... +// 50, // Number of Zones ... +// 4, // Shadow Multiplier ... +// 1, // Strength ... +// 7, // Validation Length ... +// 500 // Loopback .. +// ); + +// +// XPivot fimaPivots[]; +// int fimaPivotsCount = fimaHelper.DetecteXFIMAPivots( +// fimaPivots, +// iBar.Index(), +// 50, // Number of Pivots ... +// 7, // Validation Length ... +// 500 // Loopback ... +// ); + +// // +// has = IsValidSize(fimaZonesCount); +// if (has) +// { +// // +// // Draw Detected Zones ... +// for (int i = 0; i < fimaZonesCount; i++) +// { +// // +// XCBoxObject *iObj; +// has = poiDrawer.DrawBox( +// fimaZones[i], +// iObj, +// true, // Ignore At ... +// fimaZones[i].type // Specified Name ... +// ); +// if (has) +// { +// zoneObjects.Add(iObj); +// } +// } +// } + +// // +// has = IsValidSize(fimaPivotsCount); +// if (has) +// { +// // +// // Draw Detected Pivots ... +// for (int i = 0; i < fimaPivotsCount; i++) +// { +// // +// XCBarArrowObject *iObj; +// has = poiDrawer.DrawPivot( +// fimaPivots[i], +// iObj); +// if (has) +// { +// pivotObjects.Add(iObj); +// } +// } +// } + +// +// Detect DecisionBars ... +// XOHCL decisionBars[]; +// int decisionBarsCount = 0; +// ENUM_X_DIRECTION decisionBarDirs[]; +// decisionBarsCount = fimaHelper.DetectXFIMAPOIBars( +// decisionBars, +// decisionBarDirs, +// iBar.Index(), +// X_DIRECTION_ALL, // For Dir ... +// 300 // Required Number of Bars ... +// ); +// decisionBarsCount = fimaHelper.DetectXFIMAReversalPOIBars( +// decisionBars, +// decisionBarDirs, +// iBar.Index(), +// true, // Force Touch Boundary ... +// X_DIRECTION_ALL, // For Dir ... +// 300 // Required Number of Bars ... +// ); +// decisionBarsCount = fimaHelper.DetectXFIMAContinuationalPOIBars( +// decisionBars, +// decisionBarDirs, +// iBar.Index(), +// true, +// X_DIRECTION_ALL, // For Dir ... +// 300 // Required Number of Bars ... +// ); + +// // +// has = IsValidSize(decisionBarsCount); +// if (has) +// { +// // +// for (int i = 0; i < decisionBarsCount; i++) +// { +// // +// XCBarArrowObject *iObj; +// has = poiDrawer.DrawBarArrow( +// decisionBars[i], +// iObj, +// IsXBullish(decisionBarDirs[i]) ? X_PRICE_LOW : X_PRICE_HIGH, +// 159, +// IsXBullish(decisionBarDirs[i]) ? clrAqua : clrMagenta, +// 5, +// IsXBullish(decisionBarDirs[i]) ? ANCHOR_TOP : ANCHOR_BOTTOM, +// "XOHCL_" + ToXString(TimeToSeconds(decisionBars[i].time)), +// true, // Ignore Bar Tag ... +// 5 // Threshold ... +// ); +// if (has) +// { +// barObjects.Add(iObj); +// } +// } +// } diff --git a/BKPS/14041018/Documents/BKP/support and resistances.bkp.mq5 b/BKPS/14041018/Documents/BKP/support and resistances.bkp.mq5 new file mode 100644 index 0000000..764d816 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/support and resistances.bkp.mq5 @@ -0,0 +1,76 @@ + if (result) + { + // + XOHCL tmpBar; + int tmpIDX = -1; + bool has = false; + double upper = 0; + double lower = 0; + int length = zone.GetAge(); + + // + // Support ... + tmpIDX = bar.FindLowestIndex(length, MODE_LOW); + if (IsValidIndex(tmpIDX)) + { + // + if (tmpBar.Init(symbol, period, tmpIDX)) + { + // + lower = iLow(symbol, period, tmpIDX); + upper = bar.FindLowest(length, MODE_CLOSE); + if (upper <= lower) + { + upper = tmpBar.GetDown(); + } + + // + has = support.Init( + symbol, + period, + upper, + lower, + tmpBar.time, + bar.time, + X_DIRECTION_BULLISH, + ToXString(X_BAR_PATTERN_SUPPORT) // + ); + + // + tmpBar.Clean(); + } + } + + // + // Resistance ... + tmpIDX = bar.FindHighestIndex(length, MODE_HIGH); + if (IsValidIndex(tmpIDX)) + { + // + if (tmpBar.Init(symbol, period, tmpIDX)) + { + // + upper = iHigh(symbol, period, tmpIDX); + lower = bar.FindHighest(length, MODE_CLOSE); + if (upper <= lower) + { + upper = tmpBar.GetUp(); + } + + // + has = resistance.Init( + symbol, + period, + upper, + lower, + tmpBar.time, + bar.time, + X_DIRECTION_BEARISH, + ToXString(X_BAR_PATTERN_RESISTANCE) // + ); + + // + tmpBar.Clean(); + } + } + } diff --git a/BKPS/14041018/Documents/BKP/test-xpv.ind.mq5 b/BKPS/14041018/Documents/BKP/test-xpv.ind.mq5 new file mode 100644 index 0000000..24cd2f7 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/test-xpv.ind.mq5 @@ -0,0 +1,765 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XFIMAPV +// 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 XFIMA Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +#define ShortName "XFIMA" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Calculation ... +input group "Calculation"; +input int pvValidationLength = 7; // Peaks and Vales Validation Length +input int pvValidationCount = 2; // Recent Peak or Vale must under/over latests +input ENUM_X_PRICE peakPriceType = X_PRICE_HIGH; // Peak Calculated Price +input ENUM_X_PRICE valePriceType = X_PRICE_LOW; // Vale Calculated Price + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show Peaks and Vales +input bool showHL = true; // Show Highs and Lows +input int startCalculationForLastBars = 1500; // Calculate Last n Bars +input int peakArrowCode = 159; // Peaks Arrow Code +input int highArrowCode = 159; // Highs Arrow Code +input int valeArrowCode = 159; // Vales Arrow Code +input int lowArrowCode = 159; // Lows 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 6 +#property indicator_plots 4 + +// +// Plot Buffers ... + +// +// PEAKS ... + +// +#define peakBufferIndex 0 +double peakBuffer[]; + +// +#define peakBufferPlotIndex 0 +#property indicator_label1 "PEAK" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrMagenta +#property indicator_width1 3 + +// +// VALES ... + +// +#define valeBufferIndex 1 +double valeBuffer[]; + +// +#define valeBufferPlotIndex 1 +#property indicator_label2 "VALE" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrAqua +#property indicator_width2 3 + +// +// HIGHS ... + +// +#define highBufferIndex 2 +double highBuffer[]; + +// +#define highBufferPlotIndex 2 +#property indicator_label3 "HIGH" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrOrangeRed +#property indicator_width3 3 + +// +// LOWS ... + +// +#define lowBufferIndex 3 +double lowBuffer[]; + +// +#define lowBufferPlotIndex 3 +#property indicator_label4 "LOW" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrYellow +#property indicator_width4 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 3 + +// +#define highRawBufferIndex mLastBufferIndex + 1 +double highRawBuffer[]; + +// +#define lowRawBufferIndex mLastBufferIndex + 2 +double lowRawBuffer[]; + +// +// Variables ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + 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(); + + // + // 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 + + // + // De Initialize all Handlers and etc ... +} + +/** + * 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; +} + +// +// 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 = + // + IsXValid(peakPriceType) && + IsXValid(valePriceType) && + NotEmptyZero(pvValidationLength) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(result, pvValidationLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // PV ... + + // + 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, EMPTY_VALUE); + 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, EMPTY_VALUE); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // HL ... + + // + ENUM_DRAW_TYPE hlDrawType = showHL ? DRAW_ARROW : DRAW_NONE; + + // + // HIGH ... + + // + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(highBufferPlotIndex, PLOT_SHOW_DATA, showHL); + PlotIndexSetInteger(highBufferPlotIndex, PLOT_DRAW_TYPE, hlDrawType); + + // + PlotIndexSetDouble(highBufferPlotIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(highBufferPlotIndex, PLOT_ARROW, highArrowCode); + + // + // LOW ... + + // + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lowBufferPlotIndex, PLOT_SHOW_DATA, showHL); + PlotIndexSetInteger(lowBufferPlotIndex, PLOT_DRAW_TYPE, hlDrawType); + + // + PlotIndexSetDouble(lowBufferPlotIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(lowBufferPlotIndex, PLOT_ARROW, lowArrowCode); + + // + // Data Buffers ... + + // + ArraySetAsSeries(lowRawBuffer, true); + SetIndexBuffer(lowRawBufferIndex, lowRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(highRawBuffer, true); + SetIndexBuffer(highRawBufferIndex, highRawBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = true; + + // + // Handlers ... + + // + 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 ... + lowBuffer[barIndex] = emptyValue; + highBuffer[barIndex] = emptyValue; + peakBuffer[barIndex] = emptyValue; + valeBuffer[barIndex] = emptyValue; + highRawBuffer[barIndex] = emptyValue; + lowRawBuffer[barIndex] = emptyValue; +} + +/** + * 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[] // +) +{ + // + // Common Requirements ... + + // + FillBuffersZero(barIndex); + + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + + // + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Calculate Highs and Lows ... + XOHCL iBar; + bool has = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + if (!has) + { + return; + } + + // + int lowestIDX = -1; + double iRawLow = iBar.FindLowest( + lowestIDX, + pvValidationLength, + valePriceType // + ); + + // + int highestIDX = -1; + double iRawHigh = iBar.FindHighest( + highestIDX, + pvValidationLength, + peakPriceType // + ); + + // + lowRawBuffer[barIndex] = iRawLow; + highRawBuffer[barIndex] = iRawHigh; + + // + lowBuffer[barIndex] = iRawLow; + highBuffer[barIndex] = iRawHigh; + + // + if (barIndex < firstBarIndex - (pvValidationLength + 1)) + { + // + double tmp[]; + ArrayCopy( + tmp, + lowRawBuffer, + 0, + barIndex, + pvValidationLength // + ); + double minLow = GetMin(tmp); + bool isLow = iRawLow < minLow; + lowBuffer[barIndex] = + isLow + ? iRawLow + : lowBuffer[lastBarIndex]; + + // + XClean(tmp); + ArrayCopy( + tmp, + highRawBuffer, + 0, + barIndex, + pvValidationLength // + ); + double maxHigh = GetMax(tmp); + bool isHigh = iRawHigh > maxHigh; + highBuffer[barIndex] = + isHigh + ? iRawHigh + : highBuffer[lastBarIndex]; + + // + // Cleanup Resources ... + XClean(tmp); + } + + // // + // double iLow = emptyValue; + // // IsLow(iLow, barIndex); + // double iPLow = isFirstBar + // ? iLow + // : lowRawBuffer[lastBarIndex]; + + // // + // double iHigh = emptyValue; + // IsHigh(iHigh, barIndex); + // double iPHigh = isFirstBar + // ? iHigh + // : highRawBuffer[lastBarIndex]; + + // // + // // Clculate Values ... + + // // + // lowRawBuffer[barIndex] = iLow; + // highRawBuffer[barIndex] = iHigh; + + // // + // lowBuffer[barIndex] = NotEmptyZero(iLow) + // ? iLow + // : iPLow; + // highBuffer[barIndex] = NotEmptyZero(iHigh) + // ? iHigh + // : iPHigh; + + // // + // double iP2Low = + // barIndex < maxBarIndex - 2 + // ? lowBuffer[barIndex + 2] + // : emptyValue; + // double iP2High = + // barIndex < maxBarIndex - 2 + // ? highBuffer[barIndex + 2] + // : emptyValue; + + // // + // double mLowValues[]; + // double iVale = emptyValue; + // if (NotEmptyZero(iPLow)) + // { + // Add(iPLow, mLowValues); + // } + // if (NotEmptyZero(iP2Low)) + // { + // Add(iP2Low, mLowValues); + // } + // bool isVale = iLow <= GetMin(mLowValues); + // iVale = isVale + // ? iLow + // : isFirstBar + // ? emptyValue + // : valeBuffer[lastBarIndex]; + // valeBuffer[barIndex] = iVale; + + // // + // double mHighValues[]; + // double iPeak = emptyValue; + // if (NotEmptyZero(iPHigh)) + // { + // Add(iPHigh, mHighValues); + // } + // if (NotEmptyZero(iP2High)) + // { + // Add(iP2High, mHighValues); + // } + // bool isPeak = iHigh >= GetMax(mHighValues); + // iPeak = isPeak + // ? iHigh + // : isFirstBar + // ? emptyValue + // : peakBuffer[lastBarIndex]; + // peakBuffer[barIndex] = iPeak; + + // // + // bool has = + // NotEmptyZero(iLow) || + // NotEmptyZero(iPLow) || + // NotEmptyZero(iHigh) || + // NotEmptyZero(iPHigh); + // if (has) + // { + // } +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/test.fima.conditions.mq5 b/BKPS/14041018/Documents/BKP/test.fima.conditions.mq5 new file mode 100644 index 0000000..0e983ce --- /dev/null +++ b/BKPS/14041018/Documents/BKP/test.fima.conditions.mq5 @@ -0,0 +1,295 @@ + +// // +// isBullish = +// // +// // Vales Same ... +// sameVales >= 7 && +// // +// // PBar Patterns ... +// isBarPatternsPassed && +// isPBarCloseOverFast && +// // +// // Validate PullBack based on HK Bond ... +// isPullbackBullish && +// pBar.close > pHKBondLower; + +// +// poiDrawer.DrawPatternAnalysis( +// pBarAnalysis, +// structureDrawConfig.barAnalysisDrawConfig // +// ); + +// // +// if (IsValidSize(zonesCount)) +// { +// // +// poiDrawer.DrawZones( +// zones, +// structureDrawConfig.drawConfig // +// ); +// } + +// // +// if (IsValidSize(affectedZonesCount)) +// { +// // +// poiDrawer.DrawZones( +// affectedZones, +// structureDrawConfig.drawConfig // +// ); +// } + +// +// poiDrawer.DrawZones( +// affectedZonesBullish, +// structureDrawConfig.drawConfig // +// ); + +// // +// poiDrawer.DrawZones( +// affectedZonesBearish, +// structureDrawConfig.drawConfig // +// ); + +// // +// // Update POI Zones ... +// ENUM_X_DETECTOR_ZONE_ACTION zoneActions[]; +// poiDetector.UpdateZones( +// iBar, +// zoneActions // +// // Validation Length ... +// // Required Zones ... +// // Loopback ... +// ); + +// +// Retrieve Conditions ... +// conditions.Clean(); +// has = fimaHelper.GetConditions( +// conditions, +// barIndex, +// 10 // Loopback ... +// ); +// if (!has) +// { +// // +// iBar.Clean(); +// conditions.Clean(); + +// // +// return; +// } + +// +// structure.Clean(); +// poiDetector.AnalyseMarket( +// structure, +// structureConfig, +// barIndex // +// ); +// poiDrawer.drawnObjects.Clear(); +// poiDrawer.DrawMarketStructure( +// structure, +// structureDrawConfig // +// ); + +/** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ +bool StrategyXHasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + XOHCL continuationalBar; + XBoxZone continuationalZones[]; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Continuational Pullback ... + bool isContinuationPullBack = poiDetector.IsContinuationPullbackPattern( + pBar, + zone, + continuationalZones, + dir, + continuationalBar, + 3, // Continuational Length ... + true, // Force Continuational Loopback Has Zones ... + true, // Force Continuational Loopback Has Patterns ... + 2, // Pullback Length ... + false // Force Pullback Break ... + ); + + // + // Do ... + + // + isBullish = + // + IsXBullish(dir) && + isContinuationPullBack && + continuationalBar.GetUp() < pBar.GetDown() && + true + // isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + IsXBearish(dir) && + isContinuationPullBack && + continuationalBar.GetDown() > pBar.GetUp() && + true + // isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + // zone.to = bar.time; + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + + // + // Draw Continuational Zones ... + UpdateToTime(continuationalZones, bar.time); + poiDrawer.DrawZones(continuationalZones, structureDrawConfig.drawConfig); + + // + zone.Clean(); + + // + int idx = -1; + if (isBullish) + { + idx = GetHighestBelow(bar.GetDown(), continuationalZones); + } + else + { + idx = GetLowestAbove(bar.GetUp(), continuationalZones); + } + result = IsValidIndex(idx); + if (result) + { + zone = continuationalZones[idx]; + } + + // + if (zone.IsValid()) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.bullishColor = clrYellow; + iConfig.bearishColor = clrYellow; + poiDrawer.DrawZones(continuationalZones, iConfig); + } + + // + // Manage Stops ... + if (result) + { + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + continuationalBar.Clean(); + XClean(continuationalZones); + + // + return result; +} diff --git a/BKPS/14041018/Documents/BKP/test.fima.ind.mq5 b/BKPS/14041018/Documents/BKP/test.fima.ind.mq5 new file mode 100644 index 0000000..0f1cd20 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/test.fima.ind.mq5 @@ -0,0 +1,2523 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XFIMA +// 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 XFIMA Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +#define ShortName "XFIMA" + +// +// 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 fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 = 21; // Slow MA Length +input int maBandLength = 21; // MA Bond Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode +input bool hkIgnoreShadows = true; // HK Remove noises +input int hkSmoothingLength = 21; // HK Smoothing Length +input ENUM_X_MA_METHOD hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showHK = true; // Show HK +input bool showSAR = true; // Show Sar +input bool showHKBond = true; // Show HK Bond +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showMABand = true; // Show MA Bond +input bool showZigZag = true; // Show ZigZag +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 40 +#property indicator_plots 14 + +// +// 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, clrLime, clrLime, clrLime // clrYellow, clrOrangeRed, clrGray +#property indicator_width1 3 + +// +// 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, clrRed, clrRed, clrRed // clrLime, clrRed, clrGray +#property indicator_width2 3 + +// +// 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 Middle ... + +// +#define fiboMiddleBufferIndex 9 +#define fiboMiddleBufferPlotIndex 6 +double fiboMiddleBuffer[]; + +// +#property indicator_label7 "FIBMID" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_width7 2 + +// +// FIBO Lower ... + +// +#define fiboLowerBufferIndex 10 +#define fiboLowerBufferPlotIndex 7 +double fiboLowerBuffer[]; + +// +#property indicator_label8 "FIBLO" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrMagenta +#property indicator_width8 2 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 11 +#define zigzagBufferPlotIndex 8 +double zigzagBuffer[]; + +// +#property indicator_label9 "XZG" +#property indicator_type9 DRAW_SECTION +#property indicator_color9 clrYellow +#property indicator_width9 2 + +// +// MA Upper Boundary ... + +// +#define maUpperBufferIndex 12 +#define maUpperBufferPlotIndex 9 +double maUpperBuffer[]; + +// +#property indicator_label10 "UpperMA" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrAqua +#property indicator_width10 3 + +// +// MA Lower Boundary ... + +// +#define maLowerBufferIndex 13 +#define maLowerBufferPlotIndex 10 +double maLowerBuffer[]; + +// +#property indicator_label11 "LowerMA" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrMagenta +#property indicator_width11 3 + +// +// XHK ... + +// +#define hkOpenBufferIndex 14 +double hkOpenBuffer[]; + +// +#define hkHighBufferIndex 15 +double hkHighBuffer[]; + +// +#define hkLowBufferIndex 16 +double hkLowBuffer[]; + +// +#define hkCloseBufferIndex 17 +double hkCloseBuffer[]; + +// +#define hkColorBufferIndex 18 +double hkColorBuffer[]; + +// +#define hkBufferPlotIndex 11 +#property indicator_label12 "XHK Open;XHK High;XHK Low;XHK Close" +#property indicator_type12 DRAW_COLOR_CANDLES +#property indicator_color12 CLR_NONE, clrAqua, clrMagenta, clrGray + +// +#define hkBondUpperBufferIndex 19 +double hkBondUpperBuffer[]; + +// +#define hkBondUpperBufferPlotIndex 12 +#property indicator_label13 "UpperHK" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrAqua +#property indicator_width13 3 + +// +#define hkBondLowerBufferIndex 20 +double hkBondLowerBuffer[]; + +// +#define hkBondLowerBufferPlotIndex 13 +#property indicator_label14 "LowerHK" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrMagenta +#property indicator_width14 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 20 + +// +// 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[]; + +// +// ZigZag ... + +// +#define highsBufferIndex mLastBufferIndex + 12 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 13 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 14 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 15 +double lowsTimeBuffer[]; + +// +// XHK Data ... + +// +#define hkRawHighBufferIndex mLastBufferIndex + 16 +double hkRawHighBuffer[]; + +// +#define hkRawOpenBufferIndex mLastBufferIndex + 17 +double hkRawOpenBuffer[]; + +// +#define hkRawLowBufferIndex mLastBufferIndex + 18 +double hkRawLowBuffer[]; + +// +#define hkRawCloseBufferIndex mLastBufferIndex + 19 +double hkRawCloseBuffer[]; + +// +// 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 maUpperHandler = INVALID_HANDLE; +int maLowerHandler = INVALID_HANDLE; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Requirements ... +CArrayObj mObjects; +XCPOIDrawer *mDrawer; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; +int zigzagRecalc = 3; // Number of last extremes for recalculation + +// +double lastZigZagPeak = 0; +datetime lastZigZagPeakTime = NULL; + +// +double lastZigZagVale = 0; +datetime lastZigZagValeTime = NULL; + +// +// 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); + IndicatorRelease(maUpperHandler); + IndicatorRelease(maLowerHandler); +} + +/** + * 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // 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); + int maUpperCalculatedBars = BarsCalculated(maUpperHandler); + int maLowerCalculatedBars = BarsCalculated(maLowerHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + maUpperCalculatedBars >= maxLength && + maLowerCalculatedBars >= 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); + int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maUpperBuffer); + int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maLowerBuffer); + + // + // SAR ... + int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + copiedMAUppers >= limit && + copiedMALowers >= 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 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + 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); + result = MathMax(result, maBandLength); + + // + 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); + + // + // Middle ... + ArraySetAsSeries(fiboMiddleBuffer, true); + SetIndexBuffer(fiboMiddleBufferIndex, fiboMiddleBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboMiddleBufferPlotIndex, 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); + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Bond ... + + // + ENUM_DRAW_TYPE maBandDrawType = showMABand ? DRAW_LINE : DRAW_NONE; + + // + // MA Upper Bond ... + + // + ArraySetAsSeries(maUpperBuffer, true); + SetIndexBuffer(maUpperBufferIndex, maUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Lower Bond ... + + // + ArraySetAsSeries(maLowerBuffer, true); + SetIndexBuffer(maLowerBufferIndex, maLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // XHK ... + + // + // XHK Color ... + ArraySetAsSeries(hkColorBuffer, true); + SetIndexBuffer(hkColorBufferIndex, hkColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkOpenBuffer, true); + SetIndexBuffer(hkOpenBufferIndex, hkOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkHighBuffer, true); + SetIndexBuffer(hkHighBufferIndex, hkHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkLowBuffer, true); + SetIndexBuffer(hkLowBufferIndex, hkLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkCloseBuffer, true); + SetIndexBuffer(hkCloseBufferIndex, hkCloseBuffer, INDICATOR_DATA); + + // + // XHK Bond ... + + // + // Upper ... + ArraySetAsSeries(hkBondUpperBuffer, true); + SetIndexBuffer(hkBondUpperBufferIndex, hkBondUpperBuffer, INDICATOR_DATA); + + // + // Lower ... + ArraySetAsSeries(hkBondLowerBuffer, true); + SetIndexBuffer(hkBondLowerBufferIndex, hkBondLowerBuffer, INDICATOR_DATA); + + // + // 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); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // XHK Data ... + + // + ArraySetAsSeries(hkRawHighBuffer, true); + SetIndexBuffer(hkRawHighBufferIndex, hkRawHighBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(hkRawOpenBuffer, true); + SetIndexBuffer(hkRawOpenBufferIndex, hkRawOpenBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(hkRawLowBuffer, true); + SetIndexBuffer(hkRawLowBufferIndex, hkRawLowBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(hkRawCloseBuffer, true); + SetIndexBuffer(hkRawCloseBufferIndex, hkRawCloseBuffer, 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; + } + + // + // MA Bond Upper ... + maUpperHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_HIGH // + ); + result = maUpperHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Bond Lower ... + maLowerHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_LOW // + ); + result = maLowerHandler != 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 // + ); + + // + // XHK ... + CalculateHKBar( + 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, + fiboUpperZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboMid = GetFibonacciLevel( + iPeak, + iVale, + fiboMiddleZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboLo = GetFibonacciLevel( + iPeak, + iVale, + fiboLowerZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + fiboUpperBuffer[barIndex] = iFiboUp; + fiboMiddleBuffer[barIndex] = iFiboMid; + 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; +} + +/** + * 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 ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = zigzagDepth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < zigzagRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, zigzagDepth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, zigzagDepth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +// +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 + : hkOpenBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : hkCloseBuffer[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)); + + // + bool isBullish = iHKOpenValue < iHKCloseValue; + bool isBearish = iHKOpenValue > iHKCloseValue; + + // + if (hkIgnoreShadows) + { + // + iHKHighValue = isBullish + ? iHKCloseValue + : iHKOpenValue; + + // + iHKLowValue = isBullish + ? iHKOpenValue + : iHKCloseValue; + } + + // + // XHK Buffers ... + hkOpenBuffer[barIndex] = iHKOpenValue; + hkHighBuffer[barIndex] = iHKHighValue; + hkLowBuffer[barIndex] = iHKLowValue; + hkCloseBuffer[barIndex] = iHKCloseValue; + + // + // XHK Raw Bufferss ... + hkRawOpenBuffer[barIndex] = iHKOpenValue; + hkRawHighBuffer[barIndex] = iHKHighValue; + hkRawLowBuffer[barIndex] = iHKLowValue; + hkRawCloseBuffer[barIndex] = iHKCloseValue; + + // + // Smoothing ... + if (IsXValid(hkSmoothingMode) && hkSmoothingLength > 0) + { + // + // XHK Signal ... + + // + // High ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawHighBuffer, + hkHighBuffer, + hkSmoothingMode // + ); + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawOpenBuffer, + hkOpenBuffer, + hkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawLowBuffer, + hkLowBuffer, + hkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawCloseBuffer, + hkCloseBuffer, + hkSmoothingMode // + ); + } + + // + hkBondUpperBuffer[barIndex] = hkHighBuffer[barIndex]; + hkBondLowerBuffer[barIndex] = hkLowBuffer[barIndex]; + + // + // Calculate HK Color ... + double iHKColorValue = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + hkColorBuffer[barIndex] = + showHK + ? iHKColorValue + : hideColorIDX; +} + +// +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(); +} + +// +// +// + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/tmp-trade_symbol.info.mq5 b/BKPS/14041018/Documents/BKP/tmp-trade_symbol.info.mq5 new file mode 100644 index 0000000..ebc5440 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/tmp.backtester.codes.mq5 b/BKPS/14041018/Documents/BKP/tmp.backtester.codes.mq5 new file mode 100644 index 0000000..55c7c9a --- /dev/null +++ b/BKPS/14041018/Documents/BKP/tmp.backtester.codes.mq5 @@ -0,0 +1,1389 @@ + +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); +} + +/////////////////////////// +/// XFIMA ... +/////////////////////////// + +// +// ZIGZAG Pattern ... +// if (detectZIGZAGPatterns) +// { +// // +// // Detect Market Analysis ... +// XZigZagAnalysis zAnalysis; +// has = fima2Signaller.fimaPOIDetector.AnalyseMarketUsingZigZag( +// cBar, +// cBar.period, +// fima2Signaller.fimaHelper, +// zAnalysis, +// 15 // +// ); +// if (has) +// { +// // +// Print(ShortName + zAnalysis.GetMessage()); + +// // +// XCZigZagAnalysisObject *iObj; +// has = fima2Signaller.fimaPOIDrawer.DrawZigZagMarketAnalysisByPV( +// iObj, +// zAnalysis // +// ); +// if (has) +// { +// draws.Add(iObj); +// } +// } +// } + +// +// Reading Pivots ... +double iLows[]; +double iHighs[]; +double lowTo = 0; +double highTo = 0; +double lowFrom = 0; +double highFrom = 0; +datetime lowToTime = NULL; +datetime highToTime = NULL; +datetime lowFromTime = NULL; +datetime highFromTime = NULL; +double lowsSlope = EMPTY_VALUE; +double highsSlope = EMPTY_VALUE; +double lowsIntercept = EMPTY_VALUE; +double highsIntercept = EMPTY_VALUE; + +// +int iLoopbackLength = 50; +for (int i = 0; i < iLoopbackLength; i++) +{ + // + double iLowPrice = iLow(_Symbol, _Period, i); + double iHighPrice = iHigh(_Symbol, _Period, i); + + // + Add( + iLowPrice, + iLows // + ); + Add( + iHighPrice, + iHighs // + ); +} +has = CalculateLinearRegression( + lowsSlope, + lowsIntercept, + iLows, + 0, + 0 // +); +if (has) +{ + // + lowToTime = GetBarTime( + _Symbol, + _Period, + 0 // + ); + lowTo = CalculateValueBySlopeIntercept( + lowsSlope, + lowsIntercept, + 0 // + ); + + // + lowFromTime = GetBarTime( + _Symbol, + _Period, + iLoopbackLength // + ); + lowFrom = CalculateValueBySlopeIntercept( + lowsSlope, + lowsIntercept, + iLoopbackLength // + ); +} + +// +has = CalculateLinearRegression( + highsSlope, + highsIntercept, + iHighs, + 0, + 0 // +); +if (has) +{ + // + highToTime = GetBarTime( + _Symbol, + _Period, + 0 // + ); + highTo = CalculateValueBySlopeIntercept( + highsSlope, + highsIntercept, + 0 // + ); + + // + highFromTime = GetBarTime( + _Symbol, + _Period, + iLoopbackLength // + ); + highFrom = CalculateValueBySlopeIntercept( + highsSlope, + highsIntercept, + iLoopbackLength // + ); +} + +// +// Try to Draw ... + +// +// Low ... +CChartObjectTrend *iLowTrend; +has = fima2Signaller.fimaPOIDrawer.DrawTrendLine( + lowFrom, + lowFromTime, + lowTo, + lowToTime, + iLowTrend, + "LOW_TREMD", + true // Ray Right ... +); +if (has) +{ + draws.Add(iLowTrend); +} + +// +// High ... +CChartObjectTrend *iHighTrend; +has = fima2Signaller.fimaPOIDrawer.DrawTrendLine( + highFrom, + highFromTime, + highTo, + highToTime, + iHighTrend, + "HIGH_TREMD", + true // Ray Right ... +); +if (has) +{ + draws.Add(iHighTrend); +} + +//////////////////////////////////////////////////////// + +// +// if (HasDirection(marketStructure.signalKeyBarPatternDir)) +// { +// Print("Detected ..."); +// } +// if (marketStructure.ob.IsValid() && marketStructure.fvg.IsValid()) +// { +// Print("Detected ..."); +// } +// if (marketStructure.support.IsValid() || marketStructure.resistance.IsValid()) +// { +// // +// XOHCL pBar; +// XOHCL p2Bar; +// bool has = cBar.GetPreviousBar(pBar); +// has = has && +// pBar.GetPreviousBar(p2Bar); +// if (!has) +// { +// // +// pBar.Clean(); +// p2Bar.Clean(); +// return; +// } + +// // +// // Check For PrevZoneExistanse ... +// has = marketStructure.prevZone.IsValid(); +// if (has) { +// // +// // Draw Prev Zone ... +// XCBoxObject *iPrevZoneObj; +// marketStructure.prevZone.to = pBar.time; +// has = fima2Signaller.poiDrawer.DrawBox( +// marketStructure.prevZone, +// iPrevZoneObj // +// ); +// if (has) +// { +// // +// XPOIStyle style; +// fima2Signaller.poiDrawer.GetBoxStyle( +// style, +// marketStructure.prevZone.dir // +// ); +// style.clr = clrYellow; +// fima2Signaller.poiDrawer.ApplyBoxStyle( +// iPrevZoneObj, +// style // +// ); + +// // +// style.Clean(); +// eaDraws.Add(iPrevZoneObj); +// } +// } + +// // +// if (has) +// { +// Print("Detected ..."); +// } + +// // +// // Cleanup Resources ... +// pBar.Clean(); +// p2Bar.Clean(); +// } + +////////////////////////////////////////////////////////// + +// +XOHCL pBar; +bool has = cBar.GetPreviousBar(pBar); +if (marketStructure.isPTest) +{ + // + // Check For PrevZoneExistanse ... + has = marketStructure.pTestedZone.IsValid(); + if (has) + { + // + // Draw Prev Zone ... + XCBoxObject *iPrevZoneObj; + marketStructure.pTestedZone.to = pBar.time; + has = fima2Signaller.poiDrawer.DrawBox( + marketStructure.pTestedZone, + iPrevZoneObj // + ); + if (has) + { + // + XPOIStyle style; + fima2Signaller.poiDrawer.GetBoxStyle( + style, + marketStructure.pTestedZone.dir // + ); + style.clr = clrYellow; + fima2Signaller.poiDrawer.ApplyBoxStyle( + iPrevZoneObj, + style // + ); + + // + style.Clean(); + eaDraws.Add(iPrevZoneObj); + } + } + + // + Print("Previous Tested ..."); +} +pBar.Clean(); + +///////////////////////////////////////////////////////////// + +// +// Previous Bar must Has Support or Resistance ... + +// +// Check Supports ... +idx = GetYoungestBefore( + pForBar.time, + supports // +); +has = + pForBar.IsValid() && + IsValidIndex(idx); +if (has) +{ + pSupport = supports[idx]; +} + +// +// Check Resistances ... +idx = GetYoungestBefore( + pForBar.time, + resistances // +); +has = + pForBar.IsValid() && + IsValidIndex(idx); +if (has) +{ + pResistance = resistances[idx]; +} + +// +bool isPSupportTouched = + pSupport.IsValid() && + pForBar.low < pSupport.upper; + +// +bool isPResistanceTouched = + pResistance.IsValid() && + pForBar.high > pResistance.lower; + +// +has = + isPSupportTouched || + isPResistanceTouched; +structure.isPTest = has; +if (has) +{ + // + if (isPSupportTouched) + { + // + // Validate Previously Tested Zone Price ... + structure.pTestedZone = pSupport; + } + else if (isPResistanceTouched) + { + // + // Validate Previously Tested Zone Price ... + structure.pTestedZone = pResistance; + } + + // +} + +///////////////////////////////////////////////////////////// + +// // +// // Here We Apply Custom Detecting ... +// detectorConfig.OffDetectors(); +// detectorConfig.detectSupport = true; +// detectorConfig.detectResistance= true; +// detectorConfig.detectSignalKeyBarPattern = true; + +// // +// // Initial Bar for Analysis ... +// // at Signal Time ... +// XOHCL signalBar; +// bool isInited = signalBar.Init( +// signal.symbol, +// signal.period, +// signal.time // +// ); + +// // +// // Analyse Market ... +// fima1Signaller.poiDetector.AnalyseMarket( +// signalBar, +// marketStructure, +// detectorConfig // +// ); +// CArrayObj *iObjects; +// int drawnsCount = fima2Signaller.poiDrawer.DrawMarketStructure( +// marketStructure, +// marketStructureDrawerConfig, +// iObjects // +// ); +// if (IsValidSize(drawnsCount)) +// { +// // +// AddObjects( +// iObjects, +// eaDraws // +// ); +// } + +///////////////////////////////////////////////////////////// + +// +// On Tick Handler ... +void OnTick() +{ + // + eaIsNewBar = eaBarTracker.IsNewBar(); + bool canProcess = eaProcessAllTicks + ? true + : eaIsNewBar; + // + eaExpert.HandleOnTick(); + + // + if (!canProcess) + { + return; + } + + // + fima1Signaller.OnTick(); + fima2Signaller.OnTick(); + + // + // Initial Bar for Analysis ... + XOHCL cBar; + bool isInited = cBar.Init( + _Symbol, + _Period, + 0 // + ); + + // + // Here We Apply Custom Detecting ... + detectorConfig.OffDetectors(); + detectorConfig.detectSupport = true; + detectorConfig.detectResistance = true; + detectorConfig.detectSignalKeyBarPattern = false; + detectorConfig.supportAndResistanceValidationLength = 21; + + // + // Analyse Market ... + fima2Signaller.poiDetector.AnalyseMarket( + cBar, + marketStructure, + detectorConfig // + ); + CArrayObj *iObjects; + int drawnsCount = fima2Signaller.poiDrawer.DrawMarketStructure( + marketStructure, + marketStructureDrawerConfig, + iObjects // + ); + if (IsValidSize(drawnsCount)) + { + // + AddObjects( + iObjects, + eaDraws // + ); + } + + // + // TODO: Remove this ... + XOHCL pBar; + bool has = cBar.GetPreviousBar(pBar); + if (marketStructure.fakeBreakedZone.IsValid()) + { + // + // Check For PrevZoneExistanse ... + has = marketStructure.fakeBreakedZone.IsValid(); + if (has) + { + // + // Draw Prev Zone ... + XCBoxObject *iPrevZoneObj; + marketStructure.fakeBreakedZone.to = pBar.time; + has = fima2Signaller.poiDrawer.DrawBox( + marketStructure.fakeBreakedZone, + iPrevZoneObj // + ); + if (has) + { + // + XPOIStyle style; + fima2Signaller.poiDrawer.GetBoxStyle( + style, + marketStructure.fakeBreakedZone.dir // + ); + style.clr = clrYellow; + fima2Signaller.poiDrawer.ApplyBoxStyle( + iPrevZoneObj, + style // + ); + + // + style.Clean(); + eaDraws.Add(iPrevZoneObj); + } + } + + // + Print("Fake Breaked Detection ..."); + } + if (HasChild(marketStructure.recentlyTestedZones)) + { + // + int idx = GetYoungest(marketStructure.recentlyTestedZones); + bool has = IsValidIndex(idx); + if (has) + { + // + has = IsTested( + pBar, + marketStructure.recentlyTestedZones[idx] // + ); + } + + // + if (has) + { + Print("PrevZone Exists ..."); + } + } + pBar.Clean(); + + // + cBar.Clean(); +} + +// +void AnalyseMarket(int barIndex = 0) +{ + // + bool has = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + string symbol = fima1Signaller.symbol; + ENUM_TIMEFRAMES period = fima1Signaller.period; + + // + // Retrieve Signal Bar ... + XOHCL bar; + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // TODO: Remove this and add in OnInit() Method ... + + // + // Configuring Detector ... + + + // + detectorConfig.detectSwingTrend = true; + + // + detectorConfig.detectPinned = true; + detectorConfig.detectMomentum = true; + detectorConfig.detectEngulfed = true; + detectorConfig.detectTrueGaped = true; + + // + detectorConfig.detectStarPattern = true; + detectorConfig.detectFlagPattern = true; + detectorConfig.detectRisingPattern = true; + detectorConfig.detectPiercingPattern = true; + detectorConfig.detectSignalKeyBarPattern = true; + + // + detectorConfig.analyseFIMAPVPivots = true; + detectorConfig.analyseFIMAZigZagPivots = true; + + // + // Configure Drawer ... + + // + marketStructureDrawerConfig.drawOB = false; + marketStructureDrawerConfig.drawFVG = false; + + // + marketStructureDrawerConfig.drawPinned = false; + marketStructureDrawerConfig.drawEngulfed = true; + marketStructureDrawerConfig.drawTrueGaped = false; + marketStructureDrawerConfig.drawMomentum = false; + marketStructureDrawerConfig.drawFlagPattern = false; + marketStructureDrawerConfig.drawStarPattern = false; + marketStructureDrawerConfig.drawRisingPattern = false; + marketStructureDrawerConfig.drawPiercingPattern = false; + marketStructureDrawerConfig.drawSignalKeyBarPattern = true; + + // + // Recents ... + marketStructureDrawerConfig.drawRecentPatterns = false; + marketStructureDrawerConfig.drawFakeBreakedZone = false; + marketStructureDrawerConfig.drawRecentlyTestedZones = false; + marketStructureDrawerConfig.drawRecentlyBreakedZones = false; + + // + // XPV ... + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysis = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisZones = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisTrends = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisPivots = true; + + // + // XSAR ... + marketStructureDrawerConfig.drawFIMASARPivotsAnalysis = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisZones = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisTrends = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisPivots = false; + + // + // XZigZag ... + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysis = true; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisZones = true; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisTrends = false; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisPivots = false; + + // + // Analyse Market on Signalling Bar ... + fima1Signaller.poiDetector.AnalyseMarket( + bar, + marketStructure, + detectorConfig // + ); + + // + bar.Clean(); +} diff --git a/BKPS/14041018/Documents/BKP/tmp.codes.mq5 b/BKPS/14041018/Documents/BKP/tmp.codes.mq5 new file mode 100644 index 0000000..21a5c94 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/tmp.codes.mq5 @@ -0,0 +1,7167 @@ +// +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(); +} + +//////////////////////////////////////////////////////////////////// + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ +bool AnalysePVPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractPVPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XPV", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ +bool AnalyseMAPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractMAPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XMA", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ +bool AnalyseSARPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractSARPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XSAR", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ +bool AnalyseZigZagPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractZigZagPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XZG", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Bar ... + * + * @param structure: XFIMAMarketStructure, reference to holds result ... + * @param config: XFIMAMarketStructureConfig, reference to Configure Detector ... + * @param barIndex: int, Bar Index ... + */ +void AnalyseMarket( + XFIMAMarketStructure &structure, + XFIMAMarketStructureConfig &config, + int barIndex = 0 // +) +{ + // + // Prepare ... + structure.Clean(); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = false; + + // + has = structure.bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + structure.Clean(); + return; + } + + // + // Reading Bar Patterns ... + XOHCL iBar; + XPatternAnalysis iPatternAnalysis; + for (int i = barIndex; i < barIndex + config.loopback; i++) + { + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); + + // + // Initialize Indexed Bar ... + // + has = structure.bar.BarAt(i, iBar); + if (!has) + { + break; + } + + // + // Analyse Indexed Bar ... + has = AnalyseBarPatterns(iBar, iPatternAnalysis, config.barsAnalysisConfig); + if (has) + { + // + AddRef( + iPatternAnalysis, + structure.barsAnalysis // + ); + + // + if (i == barIndex) + { + structure.barAnalysis = iPatternAnalysis; + } + } + + // + // Check Satisfied ... + has = ArraySize(structure.barsAnalysis) >= config.requiredPivots; + if (has) + { + break; + } + } + + // + // Handle Pivot Analysis ... + + // + // XPV ... + if (config.analysePVPivots) + { + // + // Reading Pivots ... + has = AnalysePVPivots( + structure.pvAnalysis, + barIndex, + config.requiredPivots, + config.loopback, + config.pvPivotsValidationLength // + ); + if (!has) + { + structure.pvAnalysis.Clean(); + } + } + + // + // XZG ... + if (config.analyseZGPivots) + { + // + // Reading Pivots ... + has = AnalyseZigZagPivots( + structure.zgAnalysis, + barIndex, + config.requiredPivots, + config.loopback // + ); + if (!has) + { + structure.zgAnalysis.Clean(); + } + } + + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); +} + +//////////////////////////////////////////////////////////////////// + +/** + * Check Specified Bar has MA Cross or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * + * @return ( bool ) + */ +bool HasMACross( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + double validCrossDiffMultiplier = 1 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast[]; + int fastCount = CopyMAFast(barIndex, 2, fast); + + // + double slow[]; + int slowCount = CopyMASlow(barIndex, 2, slow); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(fastCount, slowCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(fast[0]) && + NotEmptyZero(fast[1]) && + NotEmptyZero(slow[0]) && + NotEmptyZero(slow[1]); + + // + isBullish = + notEmpty && + fast[0] > slow[0] && + fast[1] < slow[1]; + + // + isBearish = + notEmpty && + fast[0] < slow[0] && + fast[1] > slow[1]; + + // + result = + isBullish || + isBearish; + + // + // Validate Direction Change ... + if (result && + validCrossDiffMultiplier > 0) + { + // + double _points = GetPoints(GetSymbol()); + double diff = MathAbs(fast[0] - slow[0]); + + // + result = diff >= (validCrossDiffMultiplier * _points); + } + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + + // + return result; +} + +/** + * Check Specified Bar Price is In Boundary or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsInBoundary( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + // Read Boundary Values ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + result = value < max && + value > min; + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar Price is Over Boundary Min ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsOverBoundaryMin( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value > min; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar Price is Under Boundary Max ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsUnderBoundaryMax( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value < max; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Boundary Fake Breaked or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ +bool IsBoundaryFakeBreaked( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_CLOSE; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_CLOSE; + } + + // + // Initial Bars ... + XOHCL bar; + XOHCL pBar; + double min; + double max; + double pMin; + double pMax; + double boundaryValues[]; + result = + bar.Init( + mSymbol, + mPeriod, + barIndex // + ) && + bar.GetPreviousBar(pBar) && + GetBoundaryValues(min, max, barIndex) && + GetBoundaryValues(pMin, pMax, barIndex + 1) && + FillBoundaryValues(boundaryValues, barIndex) > 0; + + // + bool isBullish = + result && + pBar.IsBearish() && + bar.IsBullish() && + pBar.GetPrice(underMinPriceType) < pMin && + bar.GetPrice(underMinPriceType) > min && + (bar.GetPrice(underMinPriceType) > FindLesserThan(max, boundaryValues) || + bar.GetPrice(underMinPriceType) > FindBiggerThan(min + ((max - min) / 2), boundaryValues)); + + // + bool isBearish = + result && + pBar.IsBullish() && + bar.IsBearish() && + pBar.GetPrice(overMaxPriceType) > pMax && + bar.GetPrice(overMaxPriceType) < max && + (bar.GetPrice(overMaxPriceType) < FindBiggerThan(min, boundaryValues) || + bar.GetPrice(overMaxPriceType) < FindLesserThan(min + ((max - min) / 2), boundaryValues)); + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Cleanup ... + bar.Clean(); + pBar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar's Price in Hot Place or Not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ +bool IsInHotPlace( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_LOW; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_HIGH; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Initialize Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double overMaxPrice = bar.GetPrice(overMaxPriceType); + double underMinPrice = bar.GetPrice(underMinPriceType); + + // + // Reading Boundary Value ... + double min; + double max; + result = GetBoundaryValues( + min, + max, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = underMinPrice < min; + bool isBearish = overMaxPrice > max; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar price Crossed in Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsCrossedInBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Check PrevBar Is in Hot Place ... + result = IsInHotPlace( + dir, + pBarIndex, + X_PRICE_LOW, + X_PRICE_HIGH // + ); + if (!result) + { + // + dir = X_DIRECTION_NONE; + + // + return result; + } + + // + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Current Bar must Into Boundary ... + result = IsInBoundary(priceType, barIndex); + if (!result) + { + dir = X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + + // + return result; +} + +/** + * Check Specified Bar price Crossed out Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsCrossedOutBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Prev Bar Must in Boundary ... + bool isBullish = IsInBoundary(X_PRICE_LOW, pBarIndex); + bool isBearish = IsInBoundary(X_PRICE_HIGH, pBarIndex); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Current Bar must Out of Boundary ... + + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + isBullish = + result && + isBullish && + bar.IsBullish() && + !IsInBoundary(priceType, barIndex); + + // + isBearish = + result && + isBearish && + bar.IsBearish() && + !IsInBoundary(priceType, barIndex); + + // + result = isBullish || + isBearish; + if (!result) + { + // + bar.Clean(); + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar has Boundary Trend or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasBoundaryTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower); + if (!result) + { + return result; + } + + // + bool isBullish = + fast > hkBandLower && + slow > hkBandLower && + maBandUpper > hkBandLower && + maBandLower > hkBandLower && + pbBandUpper > hkBandLower && + pbBandLower > hkBandLower; + bool isBearish = + fast < hkBandUpper && + slow < hkBandUpper && + maBandUpper < hkBandUpper && + maBandLower < hkBandUpper && + pbBandUpper < hkBandUpper && + pbBandLower < hkBandUpper; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; +} + +/** + * Check Specified Bar has Boundary Trend Switched or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasBoundarySwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = HasBoundaryTrend( + dir, + barIndex // + ); + if (!result) + { + return result; + } + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + result = HasBoundaryTrend( + dir, + barIndex + 1 // + ); + if (!result) + { + return result; + } + bool isPBullish = IsXBullish(dir); + bool isPBearish = IsXBearish(dir); + + // + bool isSwitchedToBullish = + isBullish && !isPBullish; + bool isSwitchedToBearish = + isBearish && !isPBearish; + result = isSwitchedToBullish || + isSwitchedToBearish; + if (result) + { + // + dir = isSwitchedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; +} + +/** + * Check Fibo Section is Changed or not ... + * + * @param dir: reference to hold section change direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsFiboSectionChanged( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Reading Values ... + + // + double iFiboUpper = GetFiboUpper(barIndex); + double pFiboUpper = GetFiboUpper(barIndex + 1); + + // + double iFiboMiddle = GetFiboMiddle(barIndex); + double pFiboMiddle = GetFiboMiddle(barIndex + 1); + + // + double iFiboLower = GetFiboLower(barIndex); + double pFiboLower = GetFiboLower(barIndex + 1); + + // + isBullish = iFiboLower >= pFiboMiddle && + iFiboMiddle >= pFiboUpper; + isBearish = iFiboUpper <= pFiboMiddle && + iFiboMiddle <= pFiboLower; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Check for Fibo Push Exists or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold result ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ +bool HasFiboPush( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL iBar; + bool isBullish = false; + bool isBearish = false; + + // + double iFiboUpper = EMPTY_VALUE; + double pFiboUpper = EMPTY_VALUE; + + // + double iFiboMiddle = EMPTY_VALUE; + double pFiboMiddle = EMPTY_VALUE; + + // + double iFiboLower = EMPTY_VALUE; + double pFiboLower = EMPTY_VALUE; + + // + // Check Zone Validation ... + int start = barIndex; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Values ... + + // + iFiboUpper = GetFiboUpper(i); + pFiboUpper = GetFiboUpper(i + 1); + + // + iFiboMiddle = GetFiboMiddle(i); + pFiboMiddle = GetFiboMiddle(i + 1); + + // + iFiboLower = GetFiboLower(i); + pFiboLower = GetFiboLower(i + 1); + + // + result = iFiboUpper == pFiboUpper; + if (!result) + { + break; + } + } + + // + if (result) + { + // + result = iBar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + if (result) + { + // + iFiboUpper = GetFiboUpper(barIndex); + iFiboMiddle = GetFiboMiddle(barIndex); + iFiboLower = GetFiboLower(barIndex); + + // + isBullish = iBar.IsBullish() && + iBar.close > iFiboLower && + iBar.low < iFiboLower; + isBearish = iBar.IsBearish() && + iBar.close < iFiboUpper && + iBar.high > iFiboUpper; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Has Higher Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagHigherLow( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value > vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > vales[0].value && + bar.close > vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; +} + +/** + * Check Has Lower Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagLowerLow( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value < vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < vales[0].value && + bar.close < vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; +} + +/** + * Check Has Higher High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagHigherHigh( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value > peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > peaks[0].value && + bar.close > peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; +} + +/** + * Check Has Lower High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagLowerHigh( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value < peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < peaks[0].value && + bar.close < peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; +} + +// +// SAR ... + +/** + * Check Specified Bar has SAR Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasSARSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double sars[]; + int count = CopySarState(barIndex, 2, sars); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + isBullish = + sars[0] >= 1 && + sars[1] <= -1; + + // + isBearish = + sars[0] <= -1 && + sars[1] >= 1; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(sars); + + // + return result; +} + +// +// PV ... + +// +// HK ... + +/** + * Check Specified Bar has HK Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasHKSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + double open[]; + int openCount = CopyHKOpen(barIndex, 2, open); + + // + double close[]; + int closeCount = CopyHKClose(barIndex, 2, close); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(openCount, closeCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + + // + isBullish = + notEmpty && + open[0] < close[0] && + open[1] > close[1]; + + // + isBearish = + notEmpty && + open[0] > close[0] && + open[1] < close[1]; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + + // + return result; +} + +/** + * Check Specified Bar has HK Band Based Trend or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ +bool HasHKBasedTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Define Requirements ... + XOHCL iBar; + double hkUpper; + double hkLower; + bool has = false; + int bullishCount = 0; + int bearishCount = 0; + bool isBullish = false; + bool isBearish = false; + + // + // Count Bullish/Bearish Directions ... + int start = barIndex + 1; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Requirements ... + + // + // Read Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + mSymbol, + mPeriod, + i // + ); + if (!result) + { + break; + } + + // + // Reading Values ... + hkUpper = GetHKBandUpper(i); + hkLower = GetHKBandLower(i); + result = NotEmptyZero(hkUpper) && + NotEmptyZero(hkLower); + if (!result) + { + return result; + } + + // + // Check Trend ... + + // + // Bullish ... + isBullish = iBar.low > hkLower; + if (isBullish) + { + bullishCount++; + } + + // + // Bearish ... + isBearish = iBar.high < hkUpper; + if (isBearish) + { + bearishCount++; + } + + // + iBar.Clean(); + + // + } + + // + // Validate Results ... + isBullish = + bullishCount >= validationLength; + isBearish = + bearishCount >= validationLength; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + + // + // Setting Direction if Has Trend ... + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar has HK Band Based Trend Switch or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ +bool IsHKBasedTrendSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool hasTrend = HasHKBasedTrend( + dir, + barIndex, + validationLength // + ); + bool isBullish = hasTrend && + IsXBullish(dir); + bool isBearish = hasTrend && + IsXBearish(dir); + + // + bool hasPTrend = HasHKBasedTrend( + dir, + barIndex + 1, + validationLength // + ); + bool isPBullish = hasPTrend && + IsXBullish(dir); + bool isPBearish = hasPTrend && + IsXBearish(dir); + + // + dir = X_DIRECTION_NONE; + + // + // Checking Result ... + isBullish = isBullish && !isPBullish; + isBearish = isBearish && !isPBearish; + + // + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + + // + return result; +} + +/** + * Check if Price Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check if Price Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check if Price Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check if Price Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Price Switched Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Check Price Switched Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Check Price Switched Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Check Price Switched Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +// +// ZigZag Pivots With Liquidity ... + +/** + * Check ZigZag has Lower Low by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagLowerLowByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value < selected[1].value && + // + // Check Liquidity ... + selected[1].value > selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open > selected[0].value && + bar.close > selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; +} + +/** + * Check ZigZag has Higher High by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagHigherHighByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value > selected[1].value && + // + // Check Liquidity ... + selected[1].value < selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open < selected[0].value && + bar.close < selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; +} + +// +// Extractions ... + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( int ) + */ +int ExtractPVPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + bool lookupPeaks = true; + bool lookupVales = true; + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + int samePeaksCount = 0; + int sameValesCount = 0; + double tmpPeaksBuffer[]; + double tmpValesBuffer[]; + string symbol = GetSymbol(); + double iPValue = EMPTY_VALUE; + double iVValue = EMPTY_VALUE; + double pPValue = EMPTY_VALUE; + double pVValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Detecting ... + + // + // Peak ... + if (lookupPeaks) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_PEAK_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpPeaksBuffer // Buffer ... + ); + ArraySetAsSeries(tmpPeaksBuffer, true); + + // + // Reading Values ... + iPValue = tmpPeaksBuffer[0]; + pPValue = tmpPeaksBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iPValue)) + { + // + // Check New Peak ... + has = + !NotEmptyZero(pPValue) + ? true + : iPValue != pPValue; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + iPValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : samePeaksCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iPValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + samePeaksCount = 0; + } + else if (iPValue == pPValue) + { + samePeaksCount++; + } + } + } + + // + // Vale ... + if (lookupVales) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_VALE_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpValesBuffer // Buffer ... + ); + ArraySetAsSeries(tmpValesBuffer, true); + + // + // Reading Values ... + iVValue = tmpValesBuffer[0]; + pVValue = tmpValesBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iVValue)) + { + // + // Check New Vale ... + has = + !NotEmptyZero(pVValue) + ? true + : iVValue != pVValue; + if (has) + { + // + // Calculate and Validate Type ... + // Vales Only Valid when Confirmed by Bar Low ... + iType = + iVValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : sameValesCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iVValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + sameValesCount = 0; + } + else if (iVValue == pVValue) + { + sameValesCount++; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + double validCrossDiffMultiplier = 1, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double fast[]; + double slow[]; + XPivot iPivot; + int count = 0; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + double iFValue = EMPTY_VALUE; + double pFValue = EMPTY_VALUE; + double iSValue = EMPTY_VALUE; + double pSValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int fastCount = CopyMAFast(idx, 2, fast); + int slowCount = CopyMASlow(idx, 2, slow); + count = MathMin(fastCount, slowCount); + has = IsValidSize(count); + + // + // Reading Values ... + + // + iFValue = fast[0]; + pFValue = fast[1]; + + // + iSValue = slow[0]; + pSValue = slow[1]; + + // + // Validate Value ... + has = + HasMACross( + iDir, + idx, + validCrossDiffMultiplier // + ) && + NotEmptyZero(iFValue) && + NotEmptyZero(iSValue) && + NotEmptyZero(pFValue) && + NotEmptyZero(pSValue); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(iFValue, iSValue) + : MathMin(iFValue, iSValue); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_MA_CROSS); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractHKPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double open[]; + XPivot iPivot; + int count = 0; + double close[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int openCount = CopyHKOpen(idx, 2, open); + int closeCount = CopyHKClose(idx, 2, close); + count = MathMin(openCount, closeCount); + has = IsValidSize(count); + + // + // Validate Value ... + has = + HasHKSwitch( + iDir, + idx // + ) && + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_HK); + + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(open[0], close[0]) + : MathMin(open[0], close[0]); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractSARPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XOHCL pBar; + XPivot iPivot; + bool has = false; + double tmpSarBuffer[]; + int idx = barIndex - 1; + string symbol = GetSymbol(); + double iValue = EMPTY_VALUE; + double pValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + has = + has && + iBar.GetPreviousBar(pBar); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_SAR_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpSarBuffer // Buffer ... + ); + ArraySetAsSeries(tmpSarBuffer, true); + + // + // Reading Values ... + iValue = tmpSarBuffer[0]; + pValue = tmpSarBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iValue)) + { + // + // Check Sar Direction Changed ... + isSwitchedToBullish = iValue < iBar.low && + pValue > pBar.high; + isSwitchedToBearish = iValue > iBar.high && + pValue < pBar.low; + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_SAR_SWITCH); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractZigZagPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + double iValue = EMPTY_VALUE; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 1, // Number of Requirements ... + tmpZigZagBuffer // Buffer ... + ); + ArraySetAsSeries(tmpZigZagBuffer, true); + + // + // Read and Validate Value ... + iValue = tmpZigZagBuffer[0]; + has = NotEmptyZero(iValue); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Type ... + iType = + iValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : iValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Dir ... + iDir = + IsXVale(iType) + ? X_DIRECTION_BULLISH + : IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_ZIGZAG); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + return result; +} + +/** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ +int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + bool has = false; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double up = EMPTY_VALUE; + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double close = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + low = GetHKLow(i); + open = GetHKOpen(i); + high = GetHKHigh(i); + close = GetHKClose(i); + + // + // Initialized Start Bar ... + if (i == start) + { + // + startHKLow = low; + startHKOpen = open; + startHKHigh = high; + startHKClose = close; + } + + // + // Check Direction ... + isBullish = open < close; + isBearish = open > close; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Calculate Requirements for Processing ... + up = isBullish + ? close + : open; + down = isBullish + ? open + : close; + body = MathAbs(up - down); + range = high - low; + highShadow = high - up; + lowShadow = down - low; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? high + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? low + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = ToXString(XFIMA_PIVOT_HK) + "_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : ""); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + return result; +} + +// +// Values Retrievers ... + +/** + * Filling Specified Bar index Boundary Values ... + * + * @param dest: double, reference collection to hold boundary Values ... + * @param barIndex: int, Specified Bar's Index ... + * @param containsFastSlow: bool, Contains XMA Fast / Slow ... + * @param containsMABand: bool, Contains XMA Boundary Upper / Lower ... + * @param containsHKBound: bool, Contains XHK Boundary Upper / Lower ... + * @param containsPBBand: bool, Contains XPB Boundary Upper / Lower ... + * @param containsFiboLevels: nool, Contains XFIBO Levels ... + * + * @return ( int ) + */ +int FillBoundaryValues( + double &dest[], + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Read and Validate Values ... + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + has = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!has) + { + return result; + } + + // + // Fill Dest ... + + // + // XMA Fast / Slow ... + if (containsFastSlow) + { + // + Add(fast, dest); + Add(slow, dest); + } + + // + // XMA Bound ... + if (containsMABand) + { + // + Add(maBandUpper, dest); + Add(maBandLower, dest); + } + + // + // XHK Band ... + if (containsHKBound) + { + // + Add(hkBandUpper, dest); + Add(hkBandLower, dest); + } + + // + // XPB Band ... + if (containsPBBand) + { + // + Add(pbBandUpper, dest); + Add(pbBandLower, dest); + } + + // + // XFIBO Zones ... + if (containsFiboLevels) + { + // + Add(fiboLower, dest); + Add(fiboUpper, dest); + Add(fiboMiddle, dest); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Retrieve Fast, Slow, MA Band Upper/Lower, HK Band Upper/Lower and PB Band Upper/Lower Min/Max ... + * + * @param min: double, minimum value ... + * @param max: double, maximum value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool GetBoundaryValues( + double &min, + double &max, + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // +) +{ + // + bool result = false; + + // + // Prepare ... + min = EMPTY_VALUE; + max = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!result) + { + return result; + } + + // + double values[]; + + // + if (containsFastSlow) + { + // + Add(fast, values); + Add(slow, values); + } + + // + if (containsMABand) + { + // + Add(maBandUpper, values); + Add(maBandLower, values); + } + + // + if (containsHKBound) + { + // + Add(hkBandUpper, values); + Add(hkBandLower, values); + } + + // + if (containsPBBand) + { + // + Add(pbBandUpper, values); + Add(pbBandLower, values); + } + + // + if (containsFiboLevels) + { + // + Add(fiboLower, values); + Add(fiboUpper, values); + Add(fiboMiddle, values); + } + + // + result = HasChild(values); + if (!result) + { + return result; + } + + // + min = GetMin(values); + max = GetMax(values); + + // + result = + NotEmptyZero(min) && + NotEmptyZero(max) && + min < max; + + // + return result; +} diff --git a/BKPS/14041018/Documents/BKP/tmp.poi.drawer.codes.mq5 b/BKPS/14041018/Documents/BKP/tmp.poi.drawer.codes.mq5 new file mode 100644 index 0000000..520477d --- /dev/null +++ b/BKPS/14041018/Documents/BKP/tmp.poi.drawer.codes.mq5 @@ -0,0 +1,379 @@ + + /** + * 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 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; + } + + // + // Testing Draws ... + + // + XFIMAMarketStructure pivots[]; + + // + XPivot pvPivots[]; + XPivot hkPivots[]; + XPivot maPivots[]; + XPivot zgPivots[]; + XPivot sarPivots[]; + + // + poiDetector.CollectZGPivots(zgPivots); + poiDetector.CollectMAPivots(maPivots); + poiDetector.CollectHKPivots(hkPivots); + poiDetector.CollectPVPivots(pvPivots); + poiDetector.CollectSARPivots(sarPivots); + + // + // Merging All Pivots ... + Copy(pvPivots, pivots, false); + Copy(zgPivots, pivots, false); + Copy(maPivots, pivots, false); + Copy(hkPivots, pivots, false); + Copy(sarPivots, pivots, false); + + // + if (HasChild(pivots)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + // Cleanup ... + XClean(pivots); + XClean(pvPivots); + XClean(hkPivots); + XClean(maPivots); + XClean(zgPivots); + XClean(sarPivots); diff --git a/BKPS/14041018/Documents/BKP/tmp.poi.mq5 b/BKPS/14041018/Documents/BKP/tmp.poi.mq5 new file mode 100644 index 0000000..303dab0 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/tmp.poi.mq5 @@ -0,0 +1,7182 @@ +// +// 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; +} + +///////////////////////////////////////////// + +// +// Analyse Bar Patterns ... +if (result && config.analyseBarPatterns) +{ + // + // Try to Detect Bars Analysis ... + int fromIndex = -1; + if (!IsXValid(fromTime)) + { + fromIndex = barIndex + config.loopback; + } + else + { + fromIndex = GetBarIndex( + symbol, + period, + fromTime // + ); + } + result = IsValidIndex(fromIndex); + if (result) + { + // + fromIndex = MathMin(fromIndex, barIndex + config.requiredPivots); + + // + for (int i = barIndex; i < fromIndex; i++) + { + // + tmpBar.Clean(); + tmpBarAnalysis.Clean(); + result = structure.bar.BarAt(i, tmpBar); + result = result && + AnalyseBarPatterns( + tmpBar, + tmpBarAnalysis, + config.barsAnalysisConfig // + ); + if (!result) + { + break; + } + + // + AddRef( + tmpBarAnalysis, + structure.barsAnalysis // + ); + } + } +} + +//////////////////////////////////////////////// + +/** + * Draw Specified Market Structure Based on Given Configs ... + * + * @param structure: XFIMAMarketStructure, reference to Provide Specifid Market Structure ... + * @param config: XFIMAMarketStructureDrawerConfig, reference to Provide Drawing Configurations ... + */ +void DrawMarketStructure( + XFIMAMarketStructure &structure, + XFIMAMarketStructureDrawerConfig &config // +) +{ + // + // Validate ... + bool has = structure.IsValid(); + if (!has) + { + return; + } + + // + // PV Analysis ... + if (config.drawPVAnalysis) + { + // + has = structure.pvAnalysis.IsValid(); + if (has) + { + // + DrawPivotAnalysis( + structure.pvAnalysis, + config.pivotAnalysisDrawConfig // + ); + } + } + + // + // ZG Analysis ... + if (config.drawZGAnalysis) + { + // + has = structure.zgAnalysis.IsValid(); + if (has) + { + // + DrawPivotAnalysis( + structure.zgAnalysis, + config.pivotAnalysisDrawConfig // + ); + } + } + + // + // Bars Analysis ... + if (config.drawBarsAnalysis) + { + // + int count = ArraySize(structure.barsAnalysis); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + DrawPatternAnalysis( + structure.barsAnalysis[i], + config.barAnalysisDrawConfig // + ); + } + } + } +} diff --git a/BKPS/14041018/Documents/BKP/x-fima.pattern.detection.bkp.mq5 b/BKPS/14041018/Documents/BKP/x-fima.pattern.detection.bkp.mq5 new file mode 100644 index 0000000..d673406 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-fima.pattern.detection.bkp.mq5 @@ -0,0 +1,699 @@ + +/** + * Check Market Conditions for Pattern Detection ... + */ +void DetectPatterns() +{ + // + if (!eaIsNewBar) + { + 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; + + // + // XFIMA Patetrns ... + bool detectFIMAPatterns = true; + // + bool detectFIMAPVPatterns = false; + bool detectFIMAMAPatterns = false; + bool detectFIMASARPatterns = false; + bool detectFIMAZigZagPatterns = false; + // + bool analyseFIMAPVPivots = true; + bool analyseFIMAMAPivots = true; + bool analyseFIMASARPivots = true; + bool analyseFIMAZigZagPivots = true; + + // + // Required Pivots ... + int numberOfRequiredPivots = 15; + + // + // Checking Momentum Bar ... + if (detectMomentum) + { + // + bool isMomentum = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.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 = fima2Signaller.poiDrawer.DrawSwingTrend( + swings, + iDir, + iObj, + true // Ray Right ... + ); + if (has) + { + eaDraws.Add(iObj); + } + } + SpecifiedClean(swings); + } + + // + // Swing Trend Breakes ... + if (detectSwingTrendBreakes) + { + // + XOHCL swings[]; + bool hasSwingTrend = fima2Signaller.poiDetector.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 = fima2Signaller.poiDetector.HasSupport( + cBar, + support // + ); + if (hasSupport) + { + // + XBoxZone supportBox; + has = ToSupportBox(support, supportBox); + if (has) + { + // + // Draw Box ... + XCBoxObject *iObj; + has = fima2Signaller.poiDrawer.DrawBox( + supportBox, + iObj // + ); + if (has) + { + eaDraws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + supportBox.Clean(); + } + support.Clean(); + } + + // + // Detect Resistance ... + if (detectResistance) + { + // + XOHCL resistance; + bool hasResistance = fima2Signaller.poiDetector.HasResistance( + cBar, + resistance // + ); + if (hasResistance) + { + // + XBoxZone resistanceBox; + has = ToResistanceBox(resistance, resistanceBox); + if (has) + { + // + // Draw Box ... + XCBoxObject *iObj; + has = fima2Signaller.poiDrawer.DrawBox( + resistanceBox, + iObj // + ); + if (has) + { + eaDraws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + resistanceBox.Clean(); + } + resistance.Clean(); + } + + // + // Detecting FIMA Patterns ... + if (detectFIMAPatterns) + { + // + // Check For PV Pivots ... + if (detectFIMAPVPatterns) + { + // + XPivot pivots[]; + int pivotsCount = fima2Signaller.poiDetector.ExtractPVPivots( + pivots, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500, // Max Allowed Loopback ... + 10 // Validation Length ... + ); + has = IsValidSize(pivotsCount); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + int drawnPivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + has = IsValidSize(drawnPivotsCount); + if (has) + { + // + AddObjects( + drawnPivots, + eaDraws // + ); + + // + // Print("Pivots Extracted ..."); + } + + // + ZeroMemory(drawnPivots); + } + } + + // + // Check for MA Patterns ... + if (detectFIMAMAPatterns) + { + // + XPivot pivots[]; + int pivotsCount = fima2Signaller.poiDetector.ExtractMAPivots( + pivots, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500, // Max Allowed Loopback ... + 0 // Validation Length ... + ); + has = IsValidSize(pivotsCount); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + int drawnPivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + has = IsValidSize(drawnPivotsCount); + if (has) + { + // + AddObjects( + drawnPivots, + eaDraws // + ); + + // + // Print("Pivots Extracted ..."); + } + + // + ZeroMemory(drawnPivots); + } + } + + // + // Check for SAR Pivots ... + if (detectFIMASARPatterns) + { + // + XPivot pivots[]; + int pivotsCount = fima2Signaller.poiDetector.ExtractSARPivots( + pivots, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500 // Max Allowed Loopback ... + ); + has = IsValidSize(pivotsCount); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + int drawnPivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + has = IsValidSize(drawnPivotsCount); + if (has) + { + // + AddObjects( + drawnPivots, + eaDraws // + ); + + // + // Print("Pivots Extracted ..."); + } + + // + ZeroMemory(drawnPivots); + } + } + + // + // Check for ZigZag Pivots ... + if (detectFIMAZigZagPatterns) + { + // + XPivot pivots[]; + int pivotsCount = fima2Signaller.poiDetector.ExtractZigZagPivots( + pivots, + cBar.Index(), + numberOfRequiredPivots, + 1500 // + ); + has = IsValidSize(pivotsCount); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + int drawnPivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + has = IsValidSize(drawnPivotsCount); + if (has) + { + // + AddObjects( + drawnPivots, + eaDraws // + ); + + // + // Print("Pivots Extracted ..."); + } + + // + ZeroMemory(drawnPivots); + } + } + + // + // Analysers ... + + // + // Analyse Based on PV ... + if (analyseFIMAPVPivots) + { + // + XPivotAnalysis analysis; + has = fima2Signaller.poiDetector.AnalysePVPivots( + analysis, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500, // Max Allowed Loopback ... + 10 // Validation Length ... + ); + if (has) + { + // + // Draw Analysis ... + DestroyObject(pvAnalysisObject); + has = fima2Signaller.poiDrawer.DrawPivotAnalysis( + analysis, + pvAnalysisObject, + true // Draw Pivots ... + ); + if (has) + { + // + // eaDraws.Add(iObj); + + // + // Print("FIMA PV Pivots Analysed ..."); + } + } + } + + // + // Analyse Based on MA ... + if (analyseFIMAMAPivots) + { + // + XPivotAnalysis analysis; + has = fima2Signaller.poiDetector.AnalyseMAPivots( + analysis, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500, // Max Allowed Loopback ... + 0 // Validation Length ... + ); + if (has) + { + // + // Draw Analysis ... + DestroyObject(maAnalysisObject); + has = fima2Signaller.poiDrawer.DrawPivotAnalysis( + analysis, + maAnalysisObject, + true // Draw Pivots ... + ); + if (has) + { + // + // eaDraws.Add(iObj); + + // + // Print("FIMA MA Pivots Analysed ..."); + } + } + } + + // + // Analyse Based on SAR ... + if (analyseFIMASARPivots) + { + // + XPivotAnalysis analysis; + has = fima2Signaller.poiDetector.AnalyseSARPivots( + analysis, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500 // Max Allowed Loopback ... + ); + if (has) + { + // + // Draw Analysis ... + DestroyObject(sarAnalysisObject); + has = fima2Signaller.poiDrawer.DrawPivotAnalysis( + analysis, + sarAnalysisObject, + true // Draw Pivots ... + ); + if (has) + { + // + // eaDraws.Add(iObj); + + // + // Print("FIMA Sar Pivots Analysed ..."); + } + } + } + + // + // Analyse Based on ZigZag ... + if (analyseFIMAZigZagPivots) + { + // + XPivotAnalysis analysis; + has = fima2Signaller.poiDetector.AnalyseZigZagPivots( + analysis, // Result ... + cBar.Index(), // Bar Index ... + numberOfRequiredPivots, // Required Number of Pivots ... + 1500 // Max Allowed Loopback ... + ); + if (has) + { + // + // Draw Analysis ... + DestroyObject(zigzagAnalysisObject); + has = fima2Signaller.poiDrawer.DrawPivotAnalysis( + analysis, + zigzagAnalysisObject, + true // Draw Pivots ... + ); + if (has) + { + // + // eaDraws.Add(iObj); + + // + // Print("FIMA ZigZag Pivots Analysed ..."); + } + } + } + } + + // + cBar.Clean(); +} diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.x-cobject.class copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-cobject.class copy.mq5 new file mode 100644 index 0000000..e2e7bc1 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.x-cobject.class copy.mq5 @@ -0,0 +1,3787 @@ +/////////////////////////////////////////////////////// +// +// 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-pivot.analysis.lib.mq5" +#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_EMPTY_OBJ = 7860, // Empty + X_BOX_OBJ = 7861, // XBox + X_BAR_ARROW_OBJ = 7862, // XBarArrow + X_SIGNAL_OBJ = 8860, // XSignal + X_OHCL_OBJ = 8863, // XBar + X_RR_OBJ = 8864, // XRR + X_PIVOT_OBJ = 8865, // XPivot + X_POSITION_OBJ = 8866, // XPosition + // + // 9860 Custom Object ... +}; + +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; +} + +string ToXString(ENUM_XCHARTOBJECTS value) +{ + // + return EnumToString(value); +} + +struct XPOIStyle +{ + // + // Properties ... + int width; // Width ... + color clr; // Color ... + bool fill; // Fill, Use in Rectangles ... + ENUM_LINE_STYLE style; // Line Style ... + + // + // Constructor ... + XPOIStyle() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup Model ... + void Clean() + { + // + width = 1; + fill = false; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + ZeroMemory(this); + } + + // + // Default Props ... + void Default() + { + // + width = 1; + fill = false; + 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 ToXSignal( + 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; +} + +/** + * Converts a Signal to Position ... + * + * @param signal: XSignal, reference to Specified Signal ... + * @param position: XPosition, reference to Generated Position ... + * @param magic: ulong, Specified Magic Number ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ +bool ToXPosition( + XSignal &signal, + XPosition &position, + ulong magic = 0, + ulong ticket = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + position.Clean(); + + // + // Validate ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Normalize ... + + // + if (ticket <= 0) + { + // + if (signal.positionId > 0) + { + ticket = signal.positionId; + } + else + { + // + ticket = MathRand(); + signal.positionId = ticket; + } + } + signal.positionId = ticket; + + // + if (magic <= 0) + { + magic = MathRand(); + } + + // + // Filling Position ... + position.swap = 0; + position.profit = 0; + position.magic = magic; + position.commission = 0; + position.tp = signal.tp; + position.sl = signal.sl; + position.ticket = ticket; + position.type = signal.type; + position.price = signal.entry; + position.entry = signal.entry; + position.openAt = signal.time; + position.volume = signal.volume; + position.symbol = signal.symbol; + position.period = signal.period; + position.comment = signal.comment; + position.provider = signal.provider; + + // + result = position.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + position.Clean(); + } + + // + return result; +} + +/** + * Update Specified Position by Bar ... + * + * @param position: XPosition, reference to Specified Position ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool XUpdatePosition( + XPosition &position, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = position.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + position.symbol, + position.period, + barIndex // + ); + if (!result) + { + return result; + } + + // + double entryDiff = MathAbs(position.entry - position.price); + bool isLong = IsLong(position.type); + bool isInProfit = isLong + ? position.price > position.entry + : position.price < position.entry; + bool isTargeted = + isLong + ? position.price >= position.tp + : position.price <= position.tp; + bool isStoped = + isLong + ? position.price <= position.sl + : position.price >= position.sl; + result = !isTargeted && !isStoped; + if (!result) + { + return result; + } + + // + double spread = GetSpread(position.symbol); + position.price = bar.close + + (isLong + ? spread + : (-1 * spread)); + entryDiff = MathAbs(position.entry - position.price); + isInProfit = isLong + ? position.price > position.entry + : position.price < position.entry; + result = position.IsValid(); + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + +// +// Implementation ... + +// +// Global Chart Objects ... + +/** + * Base 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) + { + // + Name(value); + mObjName = value; + } + + virtual string TypeString() + { + return ToXString(X_EMPTY_OBJ); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) const + { + return ((int)X_EMPTY_OBJ); + } + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + Detach(); + Delete(); + } + + // + 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 ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mArrow.Detach(); + mArrow.Delete(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_BAR_ARROW_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_BAR_ARROW_OBJ); + } + + // + // 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 Object ... + **/ +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; + } + + // + // Virtual ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mTPTrend.Detach(); + mTPTrend.Delete(); + mSLTrend.Detach(); + mSLTrend.Delete(); + mEntryTrend.Detach(); + mEntryTrend.Delete(); + + // + mTargetTrends.Clear(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_SIGNAL_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_SIGNAL_OBJ); + } + + // + // 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); + } + + // + 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 = ToXSignal( + box, + signal, + rewardRatios // + ); + if (!result) + { + // + signal.Clean(); + + // + return result; + } + + // + result = Create( + chart_id, + window, + signal, + length, + prefix // + ); + + // + signal.Clean(); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_RR_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_RR_OBJ); + } +}; + +/** + * XOHCL 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; + } + + // + // Virtual ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mBodyRect.Detach(); + mBodyRect.Delete(); + + // + mLowShadowRect.Detach(); + mLowShadowRect.Delete(); + + // + mHighShadowRect.Detach(); + mHighShadowRect.Delete(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_OHCL_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_OHCL_OBJ); + } + + // + // 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); + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mHighShadowRect; + CChartObjectRectangle mBodyRect; + CChartObjectRectangle mLowShadowRect; +}; + +/** + * Box Object ... + **/ +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 = NULL, + 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; + } + + // + // Virtual ... + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + mAt.Detach(); + mAt.Delete(); + + // + mRect.Detach(); + mRect.Delete(); + + // + Detach(); + Delete(); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_BOX_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_BOX_OBJ); + } + + // + // 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); + } + + // + private: + // + + // + // Props ... + CChartObjectVLine mAt; + CChartObjectRectangle mRect; +}; + +/** + * Position Object ... + **/ +class XCPositionObject : public XCBaseObject +{ + // + // Public ... + public: + // + XPOIStyle riskStyle; // Risk Box Style ... + color inProfitColor; // In Profit Price Box Color ... + color inDrawdownColor; // In Drawdown Price Box Color ... + XPOIStyle rewardStyle; // Reward Box Style ... + ENUM_LINE_STYLE priceStyle; // Price Box Style ... + + // + // Creators ... + + /** + * Create a Position Object by Signal reference ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param signal: XSignal, reference to Provided Signal ... + * @param magic: ulong, Specified Position Magic Number ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XSignal &signal, + ulong magic = 0, + ulong ticket = 0 // + ) + { + // + bool result = false; + + // + // Converts Signal to Test Position ... + XPosition _position; + result = ToXPosition( + signal, + _position, + magic, + ticket // + ); + + // + // Validate ... + result = chart_id >= 0 && + window >= 0 && + _position.IsValid(); + if (!result) + { + return result; + } + + // + result = Create( + chart_id, + window, + _position // + ); + + // + return result; + } + + /** + * Create a Position Object ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = chart_id >= 0 && + window >= 0 && + position.IsValid(); + if (!result) + { + return result; + } + + // + result = Update(position); + if (!result) + { + // + Destroy(); + return result; + } + + // + return result; + } + + /** + * Update Position if Belongs to ... + * + * @param position: XPosition, reference to Specified Position ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool Update( + XPosition &position, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = + mChartID >= 0 && + mWindowID >= 0 && + position.IsValid() && + (!HasPosition() + ? true + : IsBelong(position)); + if (!result) + { + return result; + } + + // + datetime _toTime = GetBarTime( + position.symbol, + position.period, + barIndex // + ); + + // + // Validate Chart Info ... + result = UpdatePosition( + position, + _toTime // + ); + + // + return result; + } + + /** + * Update Position if Belongs to ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool Update(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + // Update mPosition ... + result = XUpdatePosition(mPosition, barIndex); + if (!result) + { + return result; + } + + // + result = Update( + mPosition, + barIndex // + ); + + // + return result; + } + + // + // Retrievers ... + + bool GetPosition(XPosition &_position) + { + // + bool result = false; + + // + // Prepare ... + _position.Clean(); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + _position = mPosition; + + // + return result; + } + + // + // Checkers ... + + /** + * Check Object is Belongs to Specified Position or not ... + * + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool IsBelong(XPosition &position) + { + // + bool result = false; + + // + // Validate ... + result = + HasPosition() && + position.IsValid(); + + // + // Check ... + result = + result && + mPosition.ticket == position.ticket; + + // + return result; + } + + // + // Overrides ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + string TypeString() override + { + return ToXString(X_POSITION_OBJ); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + int Type(void) const override + { + return ((int)X_POSITION_OBJ); + } + + /** + * Destroy Object ... + **/ + void Destroy() override + { + // + ObjName(NULL); + + // + mRiskBox.Clean(); + mPosition.Clean(); + mPriceBox.Clean(); + mRewardBox.Clean(); + + // + mRiskBoxObj.Detach(); + mRiskBoxObj.Delete(); + + // + mPriceBoxObj.Detach(); + mPriceBoxObj.Delete(); + + // + mRewardBoxObj.Detach(); + mRewardBoxObj.Delete(); + } + + // + // Stylers ... + + /** + * Apply Styles based on Current Style Configurations ... + */ + void ApplyStyle() + { + // + // Validate ... + bool has = HasPosition(); + if (!has) + { + return; + } + + // + // Check Position in Profit ... + bool isLong = IsLong(mPosition.type); + bool isRiskFreed = + isLong + ? mPosition.sl > mPosition.entry + : mPosition.sl < mPosition.entry; + bool isInProfit = mPosition.profit > 0; + XPOIStyle _priceStyle; + if (isInProfit) + { + // + _priceStyle = rewardStyle; + _priceStyle.clr = inProfitColor; + } + else + { + // + _priceStyle = riskStyle; + _priceStyle.clr = inDrawdownColor; + } + + // + // Apply Profit Based Styles ... + _priceStyle.fill = true; + _priceStyle.style = priceStyle; + + // + // Change Risk Style if Risk Freed Position ... + if (isRiskFreed) { + // + riskStyle.fill = true; + riskStyle.clr = rewardStyle.clr; + } + + // + // Risk Style ... + mRiskBoxObj.BoxColor(riskStyle.clr); + mRiskBoxObj.BoxFill(riskStyle.fill); + mRiskBoxObj.BoxStyle(riskStyle.style); + mRiskBoxObj.BoxWidth(riskStyle.width); + + // + // Reward Style ... + mRewardBoxObj.BoxColor(rewardStyle.clr); + mRewardBoxObj.BoxFill(rewardStyle.fill); + mRewardBoxObj.BoxStyle(rewardStyle.style); + mRewardBoxObj.BoxWidth(rewardStyle.width); + + // + // Price Style .. + mPriceBoxObj.BoxColor(_priceStyle.clr); + mPriceBoxObj.BoxFill(_priceStyle.fill); + mPriceBoxObj.BoxStyle(_priceStyle.style); + mPriceBoxObj.BoxWidth(_priceStyle.width); + + // + // Cleanup Resources ... + _priceStyle.Clean(); + } + + // + void ApplyStyle( + XPOIStyle &bullishStyle, + XPOIStyle &bearishStyle // + ) + { + // + // Validate ... + if (!HasPosition()) + { + return; + } + + // + // Risk Box ... + if (mRiskBox.IsValid()) + { + // + mRiskBoxObj.BoxColor(bearishStyle.clr); + mRiskBoxObj.BoxFill(bearishStyle.fill); + mRiskBoxObj.BoxStyle(bearishStyle.style); + mRiskBoxObj.BoxWidth(bearishStyle.width); + } + + // + // Reward Box ... + if (mRewardBox.IsValid()) + { + // + mRewardBoxObj.BoxColor(bullishStyle.clr); + mRewardBoxObj.BoxFill(bullishStyle.fill); + mRewardBoxObj.BoxStyle(bullishStyle.style); + mRewardBoxObj.BoxWidth(bullishStyle.width); + } + + // + // Price Box ... + if (mPriceBox.IsValid()) + { + // + XPOIStyle _priceStyle; + if (mPriceBox.IsBullish()) + { + _priceStyle = bullishStyle; + } + else + { + _priceStyle = bearishStyle; + } + + // + mPriceBoxObj.BoxColor(_priceStyle.clr); + mPriceBoxObj.BoxFill(_priceStyle.fill); + mPriceBoxObj.BoxStyle(_priceStyle.style); + mPriceBoxObj.BoxWidth(_priceStyle.width); + + // + _priceStyle.Clean(); + } + } + + // + // Protected ... + protected: + // + + // + bool HasPosition() + { + return mPosition.IsValid(); + } + + // + bool UpdatePosition( + XPosition &_position, + datetime _toTime = NULL // + ) + { + // + bool result = false; + + // + // Normalize ... + _toTime = NormalizeTime(_toTime); + + // + // Validate ... + result = _position.IsValid() && + (!HasPosition() + ? true + : _position.ticket == mPosition.ticket // + ); + if (!result) + { + return result; + } + + // + mPosition = _position; + result = UpdateZones(_toTime); + + // + return result; + } + + // + bool UpdateZones(datetime _toTime = NULL) + { + // + bool result = false; + + // + // Normalize ... + _toTime = NormalizeTime(_toTime); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + string iSymbol = mPosition.symbol; + ENUM_TIMEFRAMES iPeriod = mPosition.period; + + // + datetime iAt = mPosition.openAt; + datetime iFrom = mPosition.openAt; + + // + datetime _defaultToTime = iFrom + (PeriodSeconds(iPeriod) * 3); + datetime iTo = _toTime <= _defaultToTime + ? _defaultToTime + : _toTime; + + // + double iTP = mPosition.tp; + double iSL = mPosition.sl; + double iEntry = mPosition.entry; + double iPrice = mPosition.price; + + // + bool isLong = IsLong(mPosition.type); + ENUM_X_DIRECTION iRiskDir = isLong + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + ENUM_X_DIRECTION iRewardDir = isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + bool isInProfit = mPosition.profit > 0; + bool isRiskFreed = + isLong + ? mPosition.sl > mPosition.entry + : mPosition.sl < mPosition.entry; + ENUM_X_DIRECTION iPriceDir = isInProfit + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Try to Update Zones ... + string iSuffix = ToXString(mPosition.type) + "_" + ToXString(mPosition.ticket); + string iPrefix = ToXString(TimeToSeconds(mPosition.openAt)); + string iName = iSuffix + "_" + iPrefix; + string iRiskName = iSuffix + "_" + "RISK" + "_" + iPrefix; + string iPriceName = iSuffix + "_" + "PRICE" + "_" + iPrefix; + string iRewardName = iSuffix + "_" + "REWARD" + "_" + iPrefix; + + // + // Risk Box ... + mRiskBox.to = iTo; + mRiskBox.at = iAt; + mRiskBox.lower = + isLong + ? isRiskFreed + ? iEntry + : iSL + : isRiskFreed + ? iSL + : iEntry; + mRiskBox.upper = + isLong + ? isRiskFreed + ? iSL + : iEntry + : isRiskFreed + ? iEntry + : iSL; + mRiskBox.from = iFrom; + mRiskBox.symbol = iSymbol; + mRiskBox.period = iPeriod; + mRiskBox.type = iRiskName; + mRiskBox.dir = isRiskFreed + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + + // + // Reward Box ... + mRewardBox.to = iTo; + mRewardBox.at = iAt; + mRewardBox.lower = + isLong + ? iEntry + : iTP; + mRewardBox.upper = + isLong + ? iTP + : iEntry; + mRewardBox.from = iFrom; + mRewardBox.symbol = iSymbol; + mRewardBox.period = iPeriod; + mRewardBox.type = iRewardName; + mRewardBox.dir = X_DIRECTION_BULLISH; + + // + // Price Box ... + mPriceBox.to = iTo; + mPriceBox.at = iAt; + mPriceBox.lower = + isLong + ? isInProfit + ? isRiskFreed + ? iSL + : iEntry + : iPrice + : isInProfit + ? isRiskFreed + ? iSL + : iPrice + : iEntry; + mPriceBox.upper = + isLong + ? isInProfit + ? iPrice + : iEntry + : isInProfit + ? iEntry + : iPrice; + mPriceBox.from = iFrom; + mPriceBox.symbol = iSymbol; + mPriceBox.period = iPeriod; + mPriceBox.type = iPriceName; + mPriceBox.dir = isInProfit + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = mRiskBox.IsValid() && + mPriceBox.IsValid() && + mRewardBox.IsValid(); + if (!result) + { + return result; + } + + // + mRiskBoxObj.Detach(); + mRiskBoxObj.Delete(); + bool isRiskCreated = + mRiskBoxObj.Create( + mChartID, + mWindowID, + mRiskBox.type, + mRiskBox.upper, + mRiskBox.lower, + mRiskBox.from, + mRiskBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + mRewardBoxObj.Detach(); + mRewardBoxObj.Delete(); + bool isRewardCreated = + mRewardBoxObj.Create( + mChartID, + mWindowID, + mRewardBox.type, + mRewardBox.upper, + mRewardBox.lower, + mRewardBox.from, + mRewardBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + mPriceBoxObj.Detach(); + mPriceBoxObj.Delete(); + bool isPriceCreated = + mPriceBoxObj.Create( + mChartID, + mWindowID, + mPriceBox.type, + mPriceBox.upper, + mPriceBox.lower, + mPriceBox.from, + mPriceBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + result = + isRiskCreated && + isPriceCreated && + isRewardCreated; + if (result) + { + // + ObjName(iName); + + // + // Apply Styles ... + ApplyStyle(); + } + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + int mWindowID; + long mChartID; + + // + XBoxZone mRiskBox; + XBoxZone mPriceBox; + XPosition mPosition; + XBoxZone mRewardBox; + + // + XCBoxObject mRiskBoxObj; + XCBoxObject mPriceBoxObj; + XCBoxObject mRewardBoxObj; + + // +}; + +/** + * XPivotAnalysis Chart Object ... + **/ +class XCPivotAnalysisObject : public XCBaseObject +{ + // + public: + // + + /** + * Create Object ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param model: XPivotAnalysis, reference model ... + * @param drawTrends: Specified to Draw Trends or not ... + * @param drawZones: Specified to Draw Support and Resistance Zones or not ... + * @param drawPivots: Specified to Draw Pivots or not ... + * @param peakArrow: int, Specified Arrow Code for Peak Pivots ... + * @param valeArrow: int, Specified Arrow Code for Vale Pivots ... + * @param threshold: int, distance between price and arrow in Point ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPivotAnalysis &model, + bool drawTrends = true, + bool drawZones = true, + bool drawPivots = true, + int peakArrow = 159, + int valeArrow = 159, + int threshold = 5 // + ) + { + // + bool result = false; + + // + bool has = false; + + // + // Validate ... + result = model.IsValid(); + if (!result) + { + return result; + } + + // + // Generate Object ID ... + string objID = model.GetObjectID(); + + // + // Draw Trend Lines ... + mUpper = NULL; + mLower = NULL; + if (drawTrends) + { + // + string upperName = model.GetUpperObjectID(); + string lowerName = model.GetLowerObjectID(); + + // + RemoveObjects(upperName, chart_id, window); + RemoveObjects(lowerName, chart_id, window); + + // + // Creating Upper ... + mUpper = new CChartObjectTrend(); + result = mUpper.Create( + chart_id, + upperName, + window, + model.fromTime, + model.peakFrom, + model.toTime, + model.peakTo // + ); + if (!result) + { + // + // Destroy Trending Objects ... + DestroyObject(mUpper); + DestroyObject(mLower); + + // + return result; + } + + // + // Create Lower ... + mLower = new CChartObjectTrend(); + result = mLower.Create( + chart_id, + lowerName, + window, + model.fromTime, + model.valeFrom, + model.toTime, + model.valeTo // + ); + if (!result) + { + // + // Destroy Trending Objects ... + DestroyObject(mUpper); + DestroyObject(mLower); + + // + return result; + } + } + + // + // Draw Zones ... + mSupportBox = NULL; + mResistanceBox = NULL; + if (drawZones) + { + // + // Support ... + XBoxZone tmpBox; + has = model.HasSupportBox(tmpBox); + if (has) + { + // + datetime to = TimeCurrent(); + string name = model.GetSupportBoxObjectID(); + RemoveObjects(name, chart_id, window); + mSupportBox = new XCBoxObject(); + result = mSupportBox.Create( + chart_id, + window, + name, + tmpBox.upper, + tmpBox.lower, + tmpBox.from, + to // + ); + if (!result) + { + // + DestroyObject(mUpper); + DestroyObject(mLower); + DestroyObject(mSupportBox); + + // + return result; + } + } + + // + // Resistance ... + tmpBox.Clean(); + has = model.HasResistanceBox(tmpBox); + if (has) + { + // + datetime to = TimeCurrent(); + string name = model.GetResistanceBoxObjectID(); + RemoveObjects(name, chart_id, window); + mResistanceBox = new XCBoxObject(); + result = mResistanceBox.Create( + chart_id, + window, + name, + tmpBox.upper, + tmpBox.lower, + tmpBox.from, + to // + ); + if (!result) + { + // + DestroyObject(mUpper); + DestroyObject(mLower); + DestroyObject(mSupportBox); + DestroyObject(mResistanceBox); + + // + return result; + } + } + } + + // + // Draw Pivots ... + if (drawPivots && + model.HasPivots()) + { + // + XOHCL iBar; + int arrow = 0; + string name = NULL; + XCBarArrowObject *iObj; + ENUM_X_PRICE type = X_PRICE_NONE; + int pivotsCount = ArraySize(model.pivots); + for (int i = 0; i < pivotsCount; i++) + { + // + has = model.pivots[i].GetBar(iBar); + if (!has) + { + continue; + } + + // + arrow = model.pivots[i].IsPeak() + ? peakArrow + : valeArrow; + name = model.pivots[i].GetObjectID(); + RemoveObjects(name, chart_id, window); + type = model.pivots[i].IsPeak() + ? X_PRICE_HIGH + : X_PRICE_LOW; + iObj = new XCBarArrowObject(); + has = iObj.CreateByBar( + chart_id, + name, + window, + arrow, + iBar, + type, + threshold // + ); + if (has) + { + // + if (model.pivots[i].IsPeak()) + { + // + if (mPeaks == NULL) + { + mPeaks = new CArrayObj(); + } + + // + mPeaks.Add(iObj); + } + else + { + // + if (mVales == NULL) + { + mVales = new CArrayObj(); + } + + // + mVales.Add(iObj); + } + } + + // + iBar.Clean(); + ZeroMemory(iObj); + } + + // + // Cleanup Resources ... + iBar.Clean(); + ZeroMemory(iObj); + } + + // + // Setting Object Name ... + if (result) + { + ObjName(objID); + } + + // + return result; + } + + // + // Virtuals ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual int Type(void) + { + return (int)X_PIVOT_OBJ; + } + + /** + * Type as String ... + **/ + string TypeString() override + { + return ToXString(X_PIVOT_OBJ); + } + + /** + * Destroy ... + */ + void virtual Destroy() + { + // + DestroyObjects(mPeaks); + DestroyObjects(mVales); + + // + DestroyObject(mUpper); + DestroyObject(mLower); + DestroyObject(mSupportBox); + DestroyObject(mResistanceBox); + + // + delete mPeaks; + delete mVales; + delete mUpper; + delete mLower; + delete mSupportBox; + delete mResistanceBox; + + // + ZeroMemory(mPeaks); + ZeroMemory(mVales); + ZeroMemory(mUpper); + ZeroMemory(mLower); + ZeroMemory(mSupportBox); + ZeroMemory(mResistanceBox); + + // + Detach(); + Delete(); + } + + // + // Styling ... + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void UpperWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + if (mUpper == NULL) + { + return; + } + + // + mUpper.Width(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void UpperColor(color value) + { + // + if (mUpper == NULL) + { + return; + } + + // + mUpper.Color(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void UpperStyle(ENUM_LINE_STYLE value) + { + // + if (mUpper == NULL) + { + return; + } + + // + mUpper.Style(value); + } + + /** + * Specified Upper Ray to Left or not ... + * + * @param value: bool + */ + void UpperRayLeft(bool value) + { + // + if (mUpper == NULL) + { + return; + } + + // + mUpper.RayLeft(value); + } + + /** + * Specified Upper Ray to Right or not ... + * + * @param value: bool + */ + void UpperRayRight(bool value) + { + // + if (mUpper == NULL) + { + return; + } + + // + mUpper.RayRight(value); + } + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void LowerWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + if (mLower == NULL) + { + return; + } + + // + mLower.Width(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void LowerColor(color value) + { + // + if (mLower == NULL) + { + return; + } + + // + mLower.Color(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void LowerStyle(ENUM_LINE_STYLE value) + { + // + if (mLower == NULL) + { + return; + } + + // + mLower.Style(value); + } + + /** + * Specified Lower Ray to Left or not ... + * + * @param value: bool + */ + void LowerRayLeft(bool value) + { + // + if (mLower == NULL) + { + return; + } + + // + mLower.RayLeft(value); + } + + /** + * Specified Lower Ray to Right or not ... + * + * @param value: bool + */ + void LowerRayRight(bool value) + { + // + if (mLower == NULL) + { + return; + } + + // + mLower.RayRight(value); + } + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void SupportWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + if (mSupportBox == NULL) + { + return; + } + + // + mSupportBox.BoxWidth(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void SupportColor(color value) + { + // + if (mSupportBox == NULL) + { + return; + } + + // + mSupportBox.BoxColor(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupportStyle(ENUM_LINE_STYLE value) + { + // + if (mSupportBox == NULL) + { + return; + } + + // + mSupportBox.BoxStyle(value); + } + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void ResistanceWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + if (mResistanceBox == NULL) + { + return; + } + + // + mResistanceBox.BoxWidth(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void ResistanceColor(color value) + { + // + if (mResistanceBox == NULL) + { + return; + } + + // + mResistanceBox.BoxColor(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ResistanceStyle(ENUM_LINE_STYLE value) + { + // + if (mResistanceBox == NULL) + { + return; + } + + // + mResistanceBox.BoxStyle(value); + } + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void PeaksWidth(int value) + { + // + if (mPeaks == NULL) + { + return; + } + + // + // Normalize ... + value = NormalizeInt(value, 1); + + // + // Validate ... + int count = mPeaks.Total(); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + XCBarArrowObject *iPeak; + for (int i = 0; i < count; i++) + { + // + iPeak = (XCBarArrowObject *)mPeaks.At(i); + iPeak.ArrowWidth(value); + ZeroMemory(iPeak); + } + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void PeaksColor(color value) + { + // + if (mPeaks == NULL) + { + return; + } + + // + // Validate ... + int count = mPeaks.Total(); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + XCBarArrowObject *iPeak; + for (int i = 0; i < count; i++) + { + // + iPeak = (XCBarArrowObject *)mPeaks.At(i); + iPeak.ArrowColor(value); + ZeroMemory(iPeak); + } + } + + /** + * Set Arrow Anchor ... + * + * @param value: ENUM_ARROW_ANCHOR member ... + */ + void PeaksAnchor(ENUM_ARROW_ANCHOR value) + { + // + if (mPeaks == NULL) + { + return; + } + + // + // Validate ... + int count = mPeaks.Total(); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + XCBarArrowObject *iPeak; + for (int i = 0; i < count; i++) + { + // + iPeak = (XCBarArrowObject *)mPeaks.At(i); + iPeak.ArrowAnchor(value); + ZeroMemory(iPeak); + } + } + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void ValesWidth(int value) + { + // + if (mVales == NULL) + { + return; + } + + // + // Normalize ... + value = NormalizeInt(value, 1); + + // + // Validate ... + int count = mVales.Total(); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + XCBarArrowObject *iVale; + for (int i = 0; i < count; i++) + { + // + iVale = (XCBarArrowObject *)mVales.At(i); + iVale.ArrowWidth(value); + ZeroMemory(iVale); + } + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void ValesColor(color value) + { + // + if (mVales == NULL) + { + return; + } + + // + // Validate ... + int count = mVales.Total(); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + XCBarArrowObject *iVale; + for (int i = 0; i < count; i++) + { + // + iVale = (XCBarArrowObject *)mVales.At(i); + iVale.ArrowColor(value); + ZeroMemory(iVale); + } + } + + /** + * Set Arrow Anchor ... + * + * @param value: ENUM_ARROW_ANCHOR member ... + */ + void ValesAnchor(ENUM_ARROW_ANCHOR value) + { + // + if (mVales == NULL) + { + return; + } + + // + // Validate ... + int count = mVales.Total(); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + XCBarArrowObject *iVale; + for (int i = 0; i < count; i++) + { + // + iVale = (XCBarArrowObject *)mVales.At(i); + iVale.ArrowAnchor(value); + ZeroMemory(iVale); + } + } + + // + private: + // + CArrayObj *mPeaks; + CArrayObj *mVales; + CChartObjectTrend *mUpper; + CChartObjectTrend *mLower; + XCBoxObject *mSupportBox; + XCBoxObject *mResistanceBox; +}; + +// +// Extensions ... + +/** + * Add all Items of Specified CArrayObj into another ... + * + * @param source: CArrayObj, pointer refrence Specified Data Source ... + * @param dest: CArrayObj, pointer refrence Specified Destination of Adding ... + */ +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)); + } +} + +/** + * Destroy Object if Exists ... + * + * @param object: pointer refrence to Destroy ... + */ +void DestroyObject(XCBoxObject *&object) +{ + // + // Validate ... + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.Destroy(); + + // + object.Detach(); + object.Delete(); + + // + delete object; + ZeroMemory(object); +} + +/** + * Destroy Object if Exists ... + * + * @param object: pointer refrence to Destroy ... + */ +void DestroyObject(XCPivotAnalysisObject *&object) +{ + // + // Validate ... + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.Destroy(); + + // + object.Detach(); + object.Delete(); + + // + delete object; + ZeroMemory(object); +} + +/** + * Destroy Object if Exists ... + * + * @param object: pointer refrence to Destroy ... + */ +void DestroyObject(CChartObjectTrend *&object) +{ + // + // Validate ... + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.Detach(); + object.Delete(); + + // + delete object; + ZeroMemory(object); +} + +/** + * Completely Destroy all Chart Objects ... + * + * @param objects: CArrayObj, pointer refrence Specified Data Source ... + */ +void DestroyObjects(CArrayObj *&objects) +{ + // + // Validate Exists ... + if (objects == NULL) + { + return; + } + + // + // Count Childs ... + int count = objects.Total(); + if (!IsValidSize(count)) + { + return; + } + + // + // Destroy all Childs ... + for (int i = 0; i < count; i++) + { + // + // Checking Types ... + int iType = ((CChartObject *)objects.At(i)).Type(); + + // + string iTypeStr = NULL; + if (iType == X_EMPTY_OBJ) + { + // + XCBaseObject *iObj = (XCBaseObject *)objects.At(i); + iTypeStr = iObj.TypeString(); + + // + if (iTypeStr == ToXString(X_BOX_OBJ)) + { + iType = X_BOX_OBJ; + } + else if (iTypeStr == ToXString(X_BAR_ARROW_OBJ)) + { + iType = X_BAR_ARROW_OBJ; + } + else if (iTypeStr == ToXString(X_SIGNAL_OBJ)) + { + iType = X_SIGNAL_OBJ; + } + else if (iTypeStr == ToXString(X_OHCL_OBJ)) + { + iType = X_OHCL_OBJ; + } + else if (iTypeStr == ToXString(X_RR_OBJ)) + { + iType = X_RR_OBJ; + } + else if (iTypeStr == ToXString(X_PIVOT_OBJ)) + { + iType = X_PIVOT_OBJ; + } + } + + // + string iName = ((CChartObject *)objects.At(i)).Name(); + if (!IsSpecifiedValid(iName)) + { + iName = ((XCBaseObject *)objects.At(i)).ObjName(); + } + + // + switch (iType) + { + // + case X_RR_OBJ: { + // + XCRRObject *iObj = (XCRRObject *)objects.At(i); + iObj.Destroy(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + case X_BOX_OBJ: { + // + XCBoxObject *iObj = (XCBoxObject *)objects.At(i); + iObj.Destroy(); + iObj.Detach(); + iObj.Delete(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + case X_OHCL_OBJ: { + // + XCOHCLObject *iObj = (XCOHCLObject *)objects.At(i); + iObj.Destroy(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + case X_PIVOT_OBJ: { + // + XCPivotAnalysisObject *iObj = (XCPivotAnalysisObject *)objects.At(i); + iObj.Destroy(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + case X_SIGNAL_OBJ: { + // + XCSignalObject *iObj = (XCSignalObject *)objects.At(i); + iObj.Destroy(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + case X_BAR_ARROW_OBJ: { + // + XCBarArrowObject *iObj = (XCBarArrowObject *)objects.At(i); + iObj.Destroy(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + // + // Default Object Types ... + case OBJ_VLINE: + case OBJ_HLINE: + case OBJ_TREND: + case OBJ_TRENDBYANGLE: + case OBJ_CYCLES: + case OBJ_ARROWED_LINE: + case OBJ_CHANNEL: + case OBJ_STDDEVCHANNEL: + case OBJ_REGRESSION: + case OBJ_PITCHFORK: + case OBJ_GANNLINE: + case OBJ_GANNFAN: + case OBJ_GANNGRID: + case OBJ_FIBO: + case OBJ_FIBOTIMES: + case OBJ_FIBOFAN: + case OBJ_FIBOARC: + case OBJ_FIBOCHANNEL: + case OBJ_EXPANSION: + case OBJ_ELLIOTWAVE5: + case OBJ_ELLIOTWAVE3: + case OBJ_RECTANGLE: + case OBJ_TRIANGLE: + case OBJ_ELLIPSE: + case OBJ_ARROW_THUMB_UP: + case OBJ_ARROW_THUMB_DOWN: + case OBJ_ARROW_UP: + case OBJ_ARROW_DOWN: + case OBJ_ARROW_STOP: + case OBJ_ARROW_CHECK: + case OBJ_ARROW_LEFT_PRICE: + case OBJ_ARROW_RIGHT_PRICE: + case OBJ_ARROW_BUY: + case OBJ_ARROW_SELL: + case OBJ_ARROW: + case OBJ_TEXT: + case OBJ_LABEL: + case OBJ_BUTTON: + case OBJ_CHART: + case OBJ_BITMAP: + case OBJ_BITMAP_LABEL: + case OBJ_EDIT: + case OBJ_EVENT: + case OBJ_RECTANGLE_LABEL: { + // + CChartObject *iObj = (CChartObject *)objects.At(i); + + // + iObj.Detach(); + iObj.Delete(); + + // + delete iObj; + ZeroMemory(iObj); + } + break; + } + + // + RemoveObjects(iName); + } + + // + // Destroy itSelf ... + objects.Clear(); + delete objects; + ZeroMemory(objects); +} + +/** + * Remove Drawn Objects from Chart ... + * + * @param tag: Specified Object Name, if NULL remove all Objects ... + * @param chartId: long, Specified Chart ... + * @param subWindow: int Specified Sub Window ... + */ +void RemoveObjects( + string tag = NULL, + long chartId = -1, + int subWindow = -1 // +) +{ + // + // Normalize Args ... + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + bool has = false; + string iName = NULL; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + // Retrieve Object Name ... + iName = ObjectName(chartId, iObj, subWindow); + + // + // Check Can Delete Object or not ... + has = + !IsSpecifiedValid(tag) + ? true + : StringFind(iName, tag) >= 0; + if (has) + { + ObjectDelete(chartId, iName); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +// Color Manipulation Functions ... + +/** + * Apply Alph to Color ... + * + * @param _clr: Specified Color ... + * @param _alpha: Specified Alpha to Apply ... + * + * @return ( color ) + */ +color ApplyAlpha( + color _clr, + uchar _alpha = 255 // +) +{ + // + color result = _clr; + + // + // Normalize ... + _alpha = (uchar)NormalizeInt(_alpha, 0, 255); + + // + uchar alpha = _alpha / 255; + + // + uint uintColor = ColorToARGB(_clr, alpha); + result = (color)uintColor; + + // + return result; +} +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.x-cobject.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..91cc37c --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/x-saherelm.x-market.pattern.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-market.pattern.class.mq5 new file mode 100644 index 0000000..560cb43 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.x-market.pattern.class.mq5 @@ -0,0 +1,4780 @@ +/////////////////////////////////////////////////////// +// +// 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" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCMarketPatternDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + XBoxZone zones[]; + XBoxZone majorSupport; + XBoxZone minorSupport; + XBoxZone majorResistance; + XBoxZone minorResistance; + + // + // Constructor ... + XCMarketPatternDetector() + { + barAnalyser = new XCBarAnalyser(); + } + + // + // Deconstructor ... + ~XCMarketPatternDetector() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Actions / Helpers ... + + // + double CalculateQuarter() + { + // + double result = -1; + + // + // Validate ... + bool has = majorSupport.IsValid() && + majorResistance.IsValid(); + if (!has) + { + return result; + } + + // + result = majorSupport.upper + ((majorResistance.lower - majorSupport.upper) / 2); + + // + return result; + } + + // + // Analysers ... + + /** + * Check for Price Touch Support Level ... + * + * @param bar: XOHCL, Specified Bar ... + * @param supportBar: XOHCL, reference to holds Zone Bar ... + * @param supportBox: XBoxZone, reference to holds Zone Box ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool IsSupportTouched( + XOHCL &bar, + XOHCL &supportBar, + XBoxZone &supportBox, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + supportBar.Clean(); + supportBox.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Support Exists ... + result = HasSupport( + bar, + supportBar, + validationLength, + maxAllowedLoopback // + ); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + // Extract Support Box ... + result = ToSupportBox( + supportBar, + supportBox // + ); + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = + result && + bar.GetPreviousBar(pBar); + + // + // Chekc Price of Bar ... + result = + result && + pBar.low < supportBox.upper; + + // + // Cleanup Resources ... + if (!result) + { + // + supportBar.Clean(); + supportBox.Clean(); + } + pBar.Clean(); + + // + return result; + } + + /** + * Check for Price Touch Resistance Level ... + * + * @param bar: XOHCL, Specified Bar ... + * @param supportBar: XOHCL, reference to holds Zone Bar ... + * @param supportBox: XBoxZone, reference to holds Zone Box ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool IsResistanceTouched( + XOHCL &bar, + XOHCL &resistanceBar, + XBoxZone &resistanceBox, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + resistanceBar.Clean(); + resistanceBox.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Resistance Exists ... + result = HasResistance( + bar, + resistanceBar, + validationLength, + maxAllowedLoopback // + ); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + // Extract Resistance Box ... + result = ToResistanceBox( + resistanceBar, + resistanceBox // + ); + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = + result && + bar.GetPreviousBar(pBar); + + // + // Chekc Price of Bar ... + result = + result && + pBar.high > resistanceBox.lower; + + // + // Cleanup Resources ... + if (!result) + { + // + resistanceBar.Clean(); + resistanceBox.Clean(); + } + pBar.Clean(); + + // + return result; + } + + // + // Detectors ... + + /** + * Check Specified Bar is Peak or Vale ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ + bool IsPV( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int validationLength = 7, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, // + ENUM_X_PRICE valePriceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 2); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(peakPriceType) && + IsXValid(valePriceType); + if (!result) + { + return result; + } + + // + int valeIndex = -1; + double vale = bar.FindLowest( + valeIndex, + validationLength, + valePriceType // + ); + double barVale = bar.GetPrice(valePriceType); + bool isVale = + NotEmptyZero(vale) && + NotEmptyZero(barVale) && + IsValidIndex(valeIndex) && + vale >= barVale; + + // + int peakIndex = -1; + double peak = bar.FindHighest( + peakIndex, + validationLength, + peakPriceType // + ); + double barPeak = bar.GetPrice(peakPriceType); + bool isPeak = + NotEmptyZero(peak) && + NotEmptyZero(barPeak) && + IsValidIndex(peakIndex) && + peak <= barPeak; + + // + result = (isVale && !isPeak) || + (isPeak && !isVale); + if (result) + { + // + dir = + isVale + ? X_DIRECTION_BULLISH + : isPeak + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + + // + return result; + } + + /** + * 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: double, a Multipler for approve Momentum ... + * + * @return ( bool ) + */ + bool IsMomentumBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int requiredBars = 3, + double approvedMultiplier = 2 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + requiredBars = NormalizeInt(requiredBars, 3, 10); + approvedMultiplier = NormalizeDouble(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: double, 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, + double shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + shadowApprovedMultiplier = NormalizeDouble(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 IsStarPattern( + 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 ... + * + * @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: double, 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, + double 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; + } + + /** + * Check Specified Bar has Pullback Bar Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param pullbackLength: int, min required indirectional bars to confirm pullback ... + * @param forceBreak: bool, force pullback bar breaks peak or vale of Zone ... + * + * @return ( bool ) + */ + bool IsPullbackPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int pullbackLength = 2, + bool forceBreak = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + pullbackLength = NormalizeInt(pullbackLength, 2); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // First Bar Direction ... + dir = bar.GetDirection(); + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Loop through Pullback Length ... + XOHCL iBar; + datetime from = NULL; + double max = EMPTY_VALUE; + double min = EMPTY_VALUE; + int start = bar.Index() + 1; + int end = start + pullbackLength; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + result = bar.BarAt(i, iBar) && + iBar.GetDirection() == Opposit(dir); + if (!result) + { + break; + } + + // + // Calculate Max and Min ... + max = + !NotEmptyZero(max) + ? iBar.high + : MathMax(max, iBar.high); + min = + !NotEmptyZero(min) + ? iBar.low + : MathMin(min, iBar.low); + from = iBar.time; + } + + // + // Apply Force Break ... + if (result && + forceBreak) + { + // + result = + result && + NotEmptyZero(min) && + NotEmptyZero(max) && + (IsXBullish(dir) + ? bar.close > max + : bar.close < min); + } + + // + // Prepare Zone ... + if (result) + { + // + ToBox( + bar, + zone, + dir, + ToXString(X_BAR_PATTERN_PULLBACK) // + ); + zone.upper = max; + zone.lower = min; + zone.from = from; + zone.at = bar.time; + zone.to = bar.time; + + // + result = zone.IsValid(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + /** + * Check Market Has Consolidation Pattern or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param validationLength: int, Validation Length ... + * @param breakPriceType: ENUM_X_PRICE, Specified Price Type to Breake Consolidation ... + * @param upperPriceType: ENUM_X_PRICE, Specified Price Type to Detected Upper of Consolidation ... + * @param lowerPriceType: ENUM_X_PRICE, Specified Price Type to Detected Lower of Consolidation ... + * + * @return ( bool ) + */ + bool IsConsolidationPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int validationLength = 5, + ENUM_X_PRICE breakPriceType = X_PRICE_CLOSE, + ENUM_X_PRICE upperPriceType = X_PRICE_HIGH, + ENUM_X_PRICE lowerPriceType = X_PRICE_LOW // + ) + { + // + // Descriptions: + // =============== + // Consolidation Zones Happens by Highest High and Lowest Low + // of Specified Range which Breakes From one Side ... + // + + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(lowerPriceType) && + IsXValid(upperPriceType) && + IsXValid(breakPriceType); + if (!result) + { + return result; + } + + // + // Define Requirements ... + XOHCL iBar; + bool has = false; + datetime to = NULL; + datetime from = NULL; + double iLow = EMPTY_VALUE; + bool hasLowShadow = false; + double lower = EMPTY_VALUE; + double upper = EMPTY_VALUE; + double iHigh = EMPTY_VALUE; + bool hasHighShadow = false; + double iPrice = EMPTY_VALUE; + bool isLowerBreaked = false; + bool isUpperBreaked = false; + + // + // Loop Through Bars ... + int barIndex = bar.Index(); + int idx = barIndex; + bool canLookup = IsValidIndex(idx); + while (canLookup) + { + // + // Initialize Indexed Bar ... + idx++; + iBar.Clean(); + result = bar.BarAt(idx, iBar); + if (!result) + { + break; + } + + // + // Update Time ... + if (idx == barIndex + 1) + { + to = iBar.time; + } + + // + // Extract Low and High Price ... + iLow = iBar.GetPrice(lowerPriceType); + iHigh = iBar.GetPrice(upperPriceType); + result = NotEmptyZero(iLow) && + NotEmptyZero(iHigh); + if (!result) + { + break; + } + + // + // Check Bar Has Low/High Shadow ... + hasLowShadow = iBar.GetLowShadow() > iBar.GetHighShadow(); + hasHighShadow = iBar.GetHighShadow() > iBar.GetLowShadow(); + + // + // Update Range Lower and Upper based on Shadows ... + + // + // Lower ... + if (hasLowShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(lower) + ? true + : iLow < lower; + if (has) + { + lower = iLow; + } + } + + // + // Upper ... + if (hasHighShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(upper) + ? true + : iHigh > upper; + if (has) + { + upper = iHigh; + } + } + + // + // Check Price Breakes ... + iPrice = iBar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + if (!result) + { + break; + } + + // + // Check Upper/Lower breakes ... + isLowerBreaked = iPrice < lower; + isUpperBreaked = iPrice > upper; + + // + canLookup = (!isLowerBreaked && !isUpperBreaked); + if (!canLookup) + { + break; + } + + // + from = iBar.time; + } + + // + // Validate Calculations ... + result = + // + IsXValid(to) && + IsXValid(from) && + from < to && + // + NotEmptyZero(lower) && + NotEmptyZero(upper) && + upper > lower + // + ; + + // + // Validate To Edge Breakes ... + if (result) + { + // + iPrice = bar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + + // + // Validate To Edge Breakes ... + if (result) + { + // + isUpperBreaked = iPrice > upper; + isLowerBreaked = iPrice < lower; + + // + // Validate To Break ... + result = isUpperBreaked || isLowerBreaked; + } + + // + // Prepare Direction ... + if (result) + { + // + dir = + isUpperBreaked + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Validate Direction ... + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.to = to; + zone.dir = dir; + zone.from = from; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Validate Zone ... + result = zone.IsValid(); + + // + // Validate Zone Length ... + if (result) + { + result = zone.FromIndex() - zone.ToIndex() >= validationLength; + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + /** + * Detect Order Flow ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param orderFlow: XBoxZone, collection reference to holds Detected Order Flow ... + * @param orderFlowValidation: int, number of sequential Zones for Validate Order Flow ... + * @param containsOBs: bool, Specified to Use Order Blocks in Order Flow Detection ... + * @param containsFVGs: bool, Specified to Use Fair Value Gaps in Order Flow Detection ... + * @param containsSupportResistances: bool, Specified to Use Support and Resistances in Order Flow Detection ... + * @param zonesLoopback: int, Zone Detection Loopback ... + * @param zonesValidationLength: int, Zone Validation Length ... + * @param loopback: int, Max Allowed Loopback Bars for Collecting ... + * + * @return ( bool ) + */ + bool HasOrderFlow( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &orderFlow[], + int orderFlowValidation = 2, + bool containsOBs = false, + bool containsFVGs = true, + bool containsSupportResistances = false, + int zonesLoopback = 5, + int zonesValidationLength = 21, + int loopback = 100 // + ) + { + // + bool result = false; + + // + // Prepare ... + XClean(orderFlow); + CleanDirection(dir); + int maxRequiredZone = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + orderFlowValidation = NormalizeInt(orderFlowValidation, 1); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Collectiong Zones ... + XBoxZone tmp; + XBoxZone tmps[]; + XBoxZone _zones[]; + XBoxZone bullishZones[]; + XBoxZone bearishZones[]; + int bullishZonesCount = 0; + int bearishZonesCount = 0; + + // + // Order Blocks ... + if (containsOBs) + { + // + XClean(tmps); + CollectOBs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Fair Value Gaps ... + if (containsFVGs) + { + // + XClean(tmps); + CollectFVGs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Support and Resistances ... + if (containsSupportResistances) + { + // + XClean(tmps); + CollectZones(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Validate Zones ... + result = HasChild(_zones); + + // + // Extract Only Validated Zones ... + if (result) + { + // + ValidateBoxes( + _zones, + bar.Index() // + ); + + // + result = HasChild(_zones); + } + + // + // Separate Zones Direction ... + if (result) + { + // + bullishZonesCount = ExtractByDirection(bullishZones, _zones, X_DIRECTION_BULLISH); + bearishZonesCount = ExtractByDirection(bearishZones, _zones, X_DIRECTION_BEARISH); + + // + result = IsValidSize(bullishZonesCount) || + IsValidSize(bearishZonesCount); + } + + // + // Looking for Sequences of Zones ... + if (result) + { + // + int idx = -1; + bool has = false; + XBoxZone bullOrderFlow[]; + XBoxZone bearOrderFlow[]; + + // + // Bullish OrderFlow ... + + // + // Sorting ... + Copy(bullishZones, bullOrderFlow); + Sort( + bullOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH, + orderFlowValidation + 1 // + ); + bool hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + if (hasBullishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bullOrderFlow, tmps); + XClean(bullOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetHighest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].lower < tmp.lower; + if (has) + { + AddIfNotExists(tmp, bullOrderFlow); + } + } + + // + hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + } + + // + // Bearish OrderFlow ... + + // + // Sorting ... + Copy(bearishZones, bearOrderFlow); + Sort( + bearOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BULLISH, + orderFlowValidation + 1 // + ); + bool hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + if (hasBearishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bearOrderFlow, tmps); + XClean(bearOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetLowest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].upper > tmp.upper; + if (has) + { + AddIfNotExists(tmp, bearOrderFlow); + } + } + + // + hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + } + + // + result = hasBullishOrderFlow || + hasBearishOrderFlow; + + // + // Validate Order Flows ... + if (result) + { + // + has = (hasBullishOrderFlow && !hasBearishOrderFlow) || + (hasBearishOrderFlow && !hasBullishOrderFlow); + + // + // When only Have One Direction ... + if (has) + { + // + if (hasBullishOrderFlow) + { + // + dir = X_DIRECTION_BULLISH; + Copy(bullOrderFlow, orderFlow); + } + else if (hasBearishOrderFlow) + { + // + dir = X_DIRECTION_BEARISH; + Copy(bearOrderFlow, orderFlow); + } + } + // + // When Two Direction Exists ... + else + { + // + // Retrieve Oldest Of Bullish / Bearish ... + int oldestBullIDX = GetOldest(bullOrderFlow); + int oldestBearIDX = GetOldest(bearOrderFlow); + result = IsValidIndex(oldestBullIDX) && + IsValidIndex(oldestBearIDX); + if (result) + { + // + dir = + bullOrderFlow[oldestBullIDX].from > bearOrderFlow[oldestBearIDX].from + ? X_DIRECTION_BULLISH + : bearOrderFlow[oldestBearIDX].from > bullOrderFlow[oldestBullIDX].from + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + if (result) + { + // + if (IsXBullish(dir)) + { + Copy(bullOrderFlow, orderFlow); + } + else if (IsXBearish(dir)) + { + Copy(bearOrderFlow, orderFlow); + } + } + } + } + + // + XClean(bullOrderFlow); + XClean(bearOrderFlow); + + // + result = HasChild(orderFlow) && + HasDirection(dir); + } + + // + // Validate Price ... + if (result) + { + // + int idx = -1; + if (IsXBullish(dir)) + { + // + idx = GetHighest(orderFlow); + result = IsValidIndex(idx) && + bar.low > orderFlow[idx].upper; + } + else + { + // + idx = GetLowest(orderFlow); + result = IsValidIndex(idx) && + bar.high < orderFlow[idx].lower; + } + } + + // + // Update To Time of Order Flow ... + if (result) + { + UpdateToTime(orderFlow, bar.time); + } + + // + // Cleanup ... + if (!result) + { + // + XClean(orderFlow); + CleanDirection(dir); + } + tmp.Clean(); + XClean(tmps); + XClean(_zones); + XClean(bullishZones); + XClean(bearishZones); + + // + return result; + } + + // + // FVG ... + + /** + * Check For FVG Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param fvg: XBoxZone, reference for Holding FVG ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup FVG ... + * + * @return ( bool ) + */ + bool HasFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvg, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + fvg.Clean(); + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is FVG or not ... + has = barAnalyser.IsFVG( + iBar, + fvg, + true // Force Bar Type ... + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = fvg.dir; + + // + break; + } + + // + // Check FVG Exists ... + result = fvg.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + fvg.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + // + // OB ... + + /** + * Check For OB Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param ob: XBoxZone, reference for Holding OB ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup OB ... + * + * @return ( bool ) + */ + bool HasOB( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &ob, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + ob.Clean(); + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is OB or not ... + has = barAnalyser.IsOB( + iBar, + ob, + true, // Force FVG Bar Type ... + true // Force OB First Two Bar InDirection ... + ); + if (!has) + { + // + ob.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = ob.dir; + + // + break; + } + + // + // Check OB Exists ... + result = ob.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + ob.Clean(); + CleanDirection(dir); + } + iBar.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; + } + + /** + * Check Specified Bar Has Support or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param support: XOHCL, Supported Bar ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + 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; + } + + /** + * Check Specified Bar Has Resistance or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param resistence: XOHCL, Resistanced Bar ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + 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; + } + + // + // Analysers ... + + /** + * Analyse Specified Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param analysis: XPatternAnalysis, reference to holds Analysis result ... + * @param config: XPatternAnalysisConfig, reference to Provides Detector Configs ... + * + * @return ( bool ) + */ + bool AnalyseBarPatterns( + XOHCL &bar, + XPatternAnalysis &analysis, + XPatternAnalysisConfig &config // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + analysis.bar = bar; + analysis.time = TimeCurrent(); + + // + XOHCL iSwing; + XBoxZone iZone; + ENUM_X_DIRECTION iDir; + ENUM_X_BAR_PATTERN iPattern; + + // + bool has; + bool isBullish; + bool isBearish; + + // + bool canDetect; + bool canDetectBullish; + bool canDetectBearish; + + // + // Bars Detectors ... + + // + // XPV High Low Detection ... + canDetect = config.CanDetect(X_BAR_PATTERN_HIGH) || + config.CanDetect(X_BAR_PATTERN_LOW); + if (canDetect) + { + // + has = IsPV( + bar, + iDir, + config.pvValidationLength, + config.peakPriceType, + config.valePriceType // + ); + + // + canDetectBullish = config.CanDetect(X_BAR_PATTERN_LOW); + canDetectBearish = config.CanDetect(X_BAR_PATTERN_HIGH); + + // + isBullish = + has && + IsXBullish(iDir) && + canDetectBullish; + + // + isBearish = + has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + iPattern = + isBearish + ? X_BAR_PATTERN_HIGH + : X_BAR_PATTERN_LOW; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Momentum ... + iPattern = X_BAR_PATTERN_MOMENTUM; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsMomentumBar( + bar, + iDir, + config.momentumBarValidationLength, + config.momentumBarApprovedMultiplier // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Engulfed ... + iPattern = X_BAR_PATTERN_ENGULFED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsEngulfedBar( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // TrueGap ... + iPattern = X_BAR_PATTERN_TRUE_GAPED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsTrueGapedBar( + bar, + iDir, + config.trueGapApprovedStrength // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Pinned ... + iPattern = X_BAR_PATTERN_PINNED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsPinnedBar( + bar, + iDir, + config.pinBarShadowApprovedMultiplier, + config.pinBarRangeMultiplier, + config.pinBarForceDirection // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Pattern Detectors ... + + // + // Star ... + iPattern = X_BAR_PATTERN_STAR; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsStarPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Piercing ... + iPattern = X_BAR_PATTERN_PIERCING; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsPiercingPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Rising ... + iPattern = X_BAR_PATTERN_RISING; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsRisingPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Flag ... + iPattern = X_BAR_PATTERN_FLAG; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsFlagPattern( + bar, + iDir, + iSwing, + config.flagPatternPullbackLength // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + + // + analysis.flagSwing = iSwing; + } + } + + // + // SignalKey ... + iPattern = X_BAR_PATTERN_SIGNALKEY; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsSignalKeyBarPattern( + bar, + iDir, + config.pinBarShadowApprovedMultiplier, + config.pinBarRangeMultiplier, + config.pinBarForceDirection // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Zone Detectors ... + + // + // OB ... + iPattern = X_BAR_PATTERN_OB; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = barAnalyser.IsOB( + bar, + iZone, + config.fvgForceType, + config.obForceTwoBar // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + iZone.IsBullish() && + canDetectBullish; + isBearish = has && + iZone.IsBearish() && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.ob = iZone; + } + } + + // + // FVG ... + iPattern = X_BAR_PATTERN_FVG; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = barAnalyser.IsFVG( + bar, + iZone, + config.fvgForceType // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + iZone.IsBullish() && + canDetectBullish; + isBearish = has && + iZone.IsBearish() && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.fvg = iZone; + } + } + + // + // Support ... + iPattern = X_BAR_PATTERN_SUPPORT; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = HasSupport( + bar, + iSwing, + config.supportAndResistanceValidationLength, + config.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox( + iSwing, + iZone, + bar.time, + config.supportAndResistanceValidationLength // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.support = iZone; + } + } + } + + // + // Resistance ... + iPattern = X_BAR_PATTERN_RESISTANCE; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = HasResistance( + bar, + iSwing, + config.supportAndResistanceValidationLength, + config.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox( + iSwing, + iZone, + bar.time, + config.supportAndResistanceValidationLength // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.resistance = iZone; + } + } + } + + // + // Validate Analysis ... + result = analysis.IsValid(); + + // + // Update Quarter ... + if (result) + { + // + // Retrieve Previous Bar ... + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + // Update Quarter ... + UpdateZones( + bar, + analysis.quarterActions, + config.quarterZonesValidationLength, // Zones Validation Length ... + config.quarterZonesRequiredToStart, // Zones Count to Start Processing ... + config.quarterZoneDetectionLoopback // Zones Detection Loopback ... + ); + + // + // Fill Quarter Props ... + analysis.majorSupport = majorSupport; + analysis.minorSupport = minorSupport; + analysis.quarter = CalculateQuarter(); + analysis.majorResistance = majorResistance; + analysis.minorResistance = minorResistance; + + // + // Update To Times ... + if (analysis.majorSupport.IsValid()) + { + analysis.majorSupport.to = bar.time; + } + if (analysis.minorSupport.IsValid()) + { + analysis.minorSupport.to = bar.time; + } + if (analysis.majorResistance.IsValid()) + { + analysis.majorResistance.to = bar.time; + } + if (analysis.minorResistance.IsValid()) + { + analysis.minorResistance.to = bar.time; + } + } + } + + // + // Cleanup Resources ... + iZone.Clean(); + iSwing.Clean(); + CleanDirection(iDir); + + // + return result; + } + + /** + * Update and Manage Support and Resistance Zones ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param actions: ENUM_X_DETECTOR_ZONE_ACTION, refernce collection to Notify happens actions ... + * @param validationLength: int, Validation Length for Zones ... + * @param requiredZones: int, Number of required Zones to collecting ... + * @param loopback: int, Max Allowed Loopback Bars for Collecting ... + * + * @return ( int ) + */ + int UpdateZones( + XOHCL &bar, + ENUM_X_DETECTOR_ZONE_ACTION &actions[], + int validationLength = 3, + int requiredZones = 10, + int loopback = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(actions); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 100); + requiredZones = NormalizeInt(requiredZones, 5); + validationLength = NormalizeInt(validationLength, 2); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + int barIndex = bar.Index(); + + // + // Collect or Manage Zones ... + XOHCL zoneBar; + XBoxZone iZone; + bool hasZone = HasChild(zones); + int zonesCount = ArraySize(zones); + int zoneDetectionLoopback = (validationLength * 2); + if (!hasZone) + { + // + XOHCL iBar; + int start = barIndex; + int end = barIndex + loopback; + for (int i = start; i < end; i++) + { + // + // Extract Detected Zones ... + iBar.Clean(); + has = bar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Check Support ... + iZone.Clean(); + zoneBar.Clean(); + has = HasSupport( + iBar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToSupportBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Check Resistance ... + iZone.Clean(); + zoneBar.Clean(); + has = HasResistance( + iBar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToResistanceBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Validate Number of Zones ... + zonesCount = ArraySize(zones); + if (zonesCount >= requiredZones) + { + break; + } + } + + // + iBar.Clean(); + iZone.Clean(); + zoneBar.Clean(); + + // + // Update Has Zones ... + hasZone = HasChild(zones); + zonesCount = ArraySize(zones); + } + + // + // Manage Exists Zones ... + if (hasZone) + { + // + // Update Zones To Time ... + UpdateToTime(zones, bar.time); + + // + // Validate Zones ... + CheckZones(bar, zones); + + // + // Remove Breaked Zones ... + RemoveBreakedZones(zones); + + // + hasZone = HasChild(zones); + zonesCount = ArraySize(zones); + } + + // + // Minimum Exists Zones for Detecting majors ... + int minNumberOfZonesForMajors = 5; + bool canLookupMajor = hasZone && + zonesCount >= minNumberOfZonesForMajors; + + // + // Supports ... + + // + // Check Zones Existances ... + bool hasMajorSupport = majorSupport.IsValid(); + bool hasMinorSupport = minorSupport.IsValid(); + + // + // Check Major Support State ... + if (hasMajorSupport) + { + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + bool isBreaked = pBar.close < majorSupport.lower; + if (isBreaked) + { + // + int idx = -1; + has = FindIndex(idx, majorSupport, zones); + if (has) + { + zones[idx].breakAt = pBar.time; + } + majorSupport.Clean(); + minorSupport.Clean(); + hasMajorSupport = false; + hasMinorSupport = false; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_SUPPORT_BREAKED, + actions // + ); + } + } + + // + pBar.Clean(); + } + + // + // Look For Major Support ... + if (!hasMajorSupport) + { + // + minorSupport.Clean(); + hasMinorSupport = false; + + // + // Lookup Major ... + if (canLookupMajor) + { + // + int idx = GetLowestByDir(zones, X_DIRECTION_BULLISH); + hasMajorSupport = IsValidIndex(idx) && !IsXValid(zones[idx].breakAt); + if (hasMajorSupport) + { + // + majorSupport = zones[idx]; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_SUPPORT_DETECTED, + actions // + ); + } + } + } + + // + // Resistances ... + + // + // Check Zones Existances ... + bool hasMajorResistance = majorResistance.IsValid(); + bool hasMinorResistance = minorResistance.IsValid(); + + // + // Check Major Resistance State ... + if (hasMajorResistance) + { + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + bool isBreaked = pBar.close > majorResistance.upper; + if (isBreaked) + { + // + int idx = -1; + has = FindIndex(idx, majorResistance, zones); + if (has) + { + zones[idx].breakAt = pBar.time; + } + majorResistance.Clean(); + minorResistance.Clean(); + hasMajorResistance = false; + hasMinorResistance = false; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_RESISTANCE_BREAKED, + actions // + ); + } + } + + // + pBar.Clean(); + } + + // + // Look For Major Resistance ... + if (!hasMajorResistance) + { + // + minorResistance.Clean(); + hasMinorResistance = false; + + // + // Lookup Major ... + if (canLookupMajor) + { + // + int idx = GetHighestByDir(zones, X_DIRECTION_BEARISH); + hasMajorResistance = IsValidIndex(idx); + if (hasMajorResistance) + { + // + majorResistance = zones[idx]; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_RESISTANCE_DETECTED, + actions // + ); + } + } + } + + // + // Check Majors Exixsts ... + has = hasMajorSupport && + hasMajorResistance; + if (has) + { + // + double quarter = CalculateQuarter(); + + // + // For Looking up Minor Support, we + // have to Ensure Major Support Exists ... + if (hasMajorSupport) + { + // + majorSupport.to = bar.time; + + // + // Look for Minor Support ... + if (!hasMinorSupport) + { + // + XBoxZone _supports[]; + int _supportsCount = ExtractByDirection( + _supports, + zones, + X_DIRECTION_BULLISH // + ); + _supportsCount = RemoveBreakedZones(_supports); + has = IsValidSize(_supportsCount); + if (has) + { + // + // Remove Major ... + Remove( + majorSupport, + _supports // + ); + + // + // Count Remain Zones ... + _supportsCount = ArraySize(_supports); + has = IsValidSize(_supportsCount); + if (has) + { + // + // Minors Selected by Youngest ... + int idx = quarter > 0 + ? GetYoungestBelow(quarter, _supports) + : GetYoungest(_supports); + hasMinorSupport = IsValidIndex(idx) && !IsXValid(_supports[idx].breakAt); + if (hasMinorSupport) + { + // + minorSupport = _supports[idx]; + minorSupport.to = bar.time; + minorSupport.from = minorSupport.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_DETECTED, + actions // + ); + } + } + } + + // + XClean(_supports); + } + + // + // Validate Minor Support Place ... + if (quarter > 0 && + hasMinorSupport) + { + // + hasMinorSupport = minorSupport.upper < quarter; + if (!hasMinorSupport) + { + // + int idx = -1; + has = FindIndex( + idx, + minorSupport, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorSupport.Clean(); + } + } + + // + // Refine exists Minor Support ... + if (hasMinorSupport) + { + // + minorSupport.to = bar.time; + + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + // Check Break ... + bool isBreaked = pBar.close < minorSupport.lower; + if (isBreaked) + { + // + minorSupport.Clean(); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_BREAKED, + actions // + ); + } + + // + // Check Test ... + bool isTested = !isBreaked && + pBar.low < minorSupport.upper && + pBar.low > minorSupport.lower && + bar.close > minorSupport.lower && + bar.open > minorSupport.lower; + if (isTested) + { + // + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_RETESTED, + actions // + ); + } + + // + // Check Refine ... + bool canRefine = !isBreaked && + pBar.low < minorSupport.lower && + pBar.close > minorSupport.lower; + if (canRefine) + { + // + minorSupport.upper = minorSupport.lower; + minorSupport.lower = pBar.low; + Add( + pBar.time, + minorSupport.refines // + ); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_REFINED, + actions // + ); + } + + // + // Check New Minor Support ... + has = !isTested && + !canRefine; + if (has) + { + // + // Check Above Minor Support has Support ... + XBoxZone _supports[]; + int _supportsCount = ExtractByDirection( + _supports, + zones, + X_DIRECTION_BULLISH // + ); + Remove(majorSupport, _supports); + Remove(minorSupport, _supports); + RemoveBreakedZones(_supports); + _supportsCount = ArraySize(_supports); + has = IsValidSize(_supportsCount); + if (has) + { + // + int idx = GetLowestAfter(minorSupport.from, _supports); + hasMinorSupport = IsValidIndex(idx) && + (quarter <= 0 + ? true + : _supports[idx].upper < quarter); + if (hasMinorSupport) + { + // + minorSupport = _supports[idx]; + minorSupport.to = bar.time; + minorSupport.from = minorSupport.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_DETECTED, + actions // + ); + } + } + } + } + + // + pBar.Clean(); + } + } + + // + // For Looking up Minor Resistance, we + // have to Ensure Major Resistance Exists ... + if (hasMajorResistance) + { + // + majorResistance.to = bar.time; + + // + // Look for Minor Resistance ... + if (!hasMinorResistance) + { + // + XBoxZone _resistances[]; + int _resistancesCount = ExtractByDirection( + _resistances, + zones, + X_DIRECTION_BEARISH // + ); + _resistancesCount = RemoveBreakedZones(_resistances); + has = IsValidSize(_resistancesCount); + if (has) + { + // + // Remove Major ... + Remove( + majorResistance, + _resistances // + ); + + // + // Count Remain Zones ... + _resistancesCount = ArraySize(_resistances); + has = IsValidSize(_resistancesCount); + if (has) + { + // + // Minors Selected Youngest ... + int idx = GetYoungestAbove(quarter, _resistances); + hasMinorResistance = IsValidIndex(idx); + if (hasMinorResistance) + { + // + minorResistance = _resistances[idx]; + minorResistance.to = bar.time; + minorResistance.from = minorResistance.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_DETECTED, + actions // + ); + } + } + } + + // + XClean(_resistances); + } + + // + // Validate Minor Support Place ... + if (quarter > 0 && + hasMinorResistance) + { + // + hasMinorResistance = minorResistance.lower > quarter; + if (!hasMinorResistance) + { + // + int idx = -1; + has = FindIndex( + idx, + minorResistance, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorResistance.Clean(); + } + } + + // + // Refine exists Minor Resistance ... + if (hasMinorResistance) + { + // + minorResistance.to = bar.time; + + // + // Check Retesting ... + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + // Check Break ... + bool isBreaked = pBar.close > minorResistance.upper; + if (isBreaked) + { + // + minorResistance.Clean(); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_BREAKED, + actions // + ); + } + + // + // Check Test ... + bool isTested = !isBreaked && + pBar.high > minorResistance.lower && + pBar.high < minorResistance.upper && + bar.close < minorResistance.upper && + bar.open < minorResistance.upper; + if (isTested) + { + // + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_RETESTED, + actions // + ); + } + + // + // Check Refine ... + bool canRefine = !isBreaked && + pBar.high > minorResistance.upper && + pBar.close < minorResistance.upper; + if (canRefine) + { + // + minorResistance.lower = minorResistance.upper; + minorResistance.upper = pBar.high; + Add( + pBar.time, + minorResistance.refines // + ); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_REFINED, + actions // + ); + } + + // + // Check New Minor Resistace ... + has = !isTested && + !canRefine; + if (has) + { + // + // Check Above Minor Resistance has Resistance ... + XBoxZone _resistances[]; + int _resistancesCount = ExtractByDirection( + _resistances, + zones, + X_DIRECTION_BEARISH // + ); + Remove(majorResistance, _resistances); + Remove(minorResistance, _resistances); + RemoveBreakedZones(_resistances); + _resistancesCount = ArraySize(_resistances); + has = IsValidSize(_resistancesCount); + if (has) + { + // + int idx = GetHighestAfter(minorResistance.from, _resistances); + hasMinorResistance = IsValidIndex(idx) && + (quarter <= 0 + ? true + : _resistances[idx].lower > quarter); + if (hasMinorResistance) + { + // + minorResistance = _resistances[idx]; + minorResistance.to = bar.time; + minorResistance.from = minorResistance.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_DETECTED, + actions // + ); + } + } + } + } + + // + pBar.Clean(); + } + } + } + else + { + // + int idx = -1; + + // + has = minorSupport.IsValid() && + FindIndex( + idx, + minorSupport, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorSupport.Clean(); + hasMinorSupport = false; + + // + has = minorResistance.IsValid() && + FindIndex( + idx, + minorResistance, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorResistance.Clean(); + hasMinorResistance = false; + } + + // + // Check Bar Zones to Update Zones ... + + // + // Check Support ... + iZone.Clean(); + zoneBar.Clean(); + has = HasSupport( + bar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToSupportBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Check Resistance ... + iZone.Clean(); + zoneBar.Clean(); + has = HasResistance( + bar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToResistanceBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Actions Counting ... + result = ArraySize(actions); + + // + // Cleanup ... + iZone.Clean(); + zoneBar.Clean(); + + // + return result; + } + + int CollectOBs( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + ENUM_X_DIRECTION iDir; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + has = bar.BarAt(i, iBar); + has = has && + HasOB(iBar, iDir, iBox, zonesLoopback); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + return result; + } + + int CollectFVGs( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + ENUM_X_DIRECTION iDir; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + has = bar.BarAt(i, iBar); + has = has && + HasFVG(iBar, iDir, iBox, zonesLoopback); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + return result; + } + + int CollectZones( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int zonesValidationLength = 21, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + XOHCL iZoneBar; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iZoneBar.Clean(); + + // + has = bar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Support ... + has = HasSupport(iBar, iZoneBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToSupportBox(iZoneBar, iBox, bar.time, zonesValidationLength); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + } + + // + // Resistance ... + has = HasResistance(iBar, iZoneBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToResistanceBox(iZoneBar, iBox, bar.time, zonesValidationLength); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iZoneBar.Clean(); + + // + return result; + } + + /** + * Filter Zones ... + * + * @param bar: XOHCL, reference to Specified Filtering Bar ... + * @param source: XBoxZone, reference collection to hold's filtered zones ... + * @param filterDir: ENUM_X_DIRECTION, specified Filter Direction ... + * @param priceType: ENUM_X_PRICE, Specified Bar's Price type to Use for Filtering Zones ... + * @param forDir: ENUM_X_DIRECTION, Specified Zone's Direction to Handle Filtering ... + * + * @return ( int ) + */ + int FilterZones( + XOHCL &bar, + XBoxZone &source[], + ENUM_X_DIRECTION filterDir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XBoxZone tmp[]; + Copy( + source, + tmp // + ); + XClean(source); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(tmp) && + IsXValid(priceType) && + HasDirection(filterDir); + if (!has) + { + // + XClean(tmp); + return result; + } + + // + XBoxZone iBox; + double price = bar.GetPrice(priceType); + bool isBullish = IsXBullish(filterDir); + while (HasChild(tmp)) + { + // + iBox = tmp[0]; + ArrayRemove(tmp, 0, 1); + + // + has = + // + // Direction Pass ... + (!HasDirection(forDir) + ? true + : forDir == iBox.dir) + // + && + // + // Price Pass ... + (isBullish + ? price > iBox.lower + : price < iBox.upper); + if (has) + { + AddIfNotExists(iBox, source); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(source); + + // + // Cleanup ... + XClean(tmp); + iBox.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Tools / Actions ... + + /** + * Check Zones and Manage them ... + * + * @param forBar: XOHCL, reference to Specified Bar ... + * @param _zones: XBoxZone, reference to Specified Zone Collection ... + * @param sortBy: X_SORT_BY_DATE, Sort Zones by ... + * @param sortDir: ENUM_X_DIRECTION, Sort Zones in Direction ... + * @param maxAllowed: int, Specified Max Allowed Zones ... + */ + void CheckZones( + XOHCL &forBar, + XBoxZone &_zones[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH, + int maxAllowed = 50 // + ) + { + // + // Normalize ... + maxAllowed = NormalizeInt(maxAllowed, 0); + + // + // Validate ... + bool has = forBar.IsValid() && + HasChild(_zones); + if (!has) + { + return; + } + + // + // Looping Through Zones ... + int count = ArraySize(_zones); + for (int i = 0; i < count; i++) + { + // + // Check Break ... + has = IsXValid(_zones[i].breakAt); + if (has) + { + continue; + } + + // + _zones[i].to = forBar.time; + + // + // Check for Test ... + has = IsTested( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].tests // + ); + } + + // + // Check for Inside ... + has = IsInside( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].insides // + ); + } + + // + // Check for Break ... + has = IsBreaked( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].breaks // + ); + } + + // + // Check for Act ... + has = IsActed( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].acteds // + ); + } + + // + // Check for FakeBreakes ... + has = IsFakeBreaked( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].fakeBreaks // + ); + } + + // + // Check for Valid Breakes ... + has = IsValidBreaked( + forBar, + _zones[i] // + ); + if (has) + { + _zones[i].breakAt = forBar.time; + } + } + + // + // Apply Sort and Cleanup ... + Sort( + _zones, + sortBy, + sortDir, + maxAllowed // + ); + } + + // + // Private ... + private: + // + // Props ... + XCBarAnalyser *barAnalyser; + + // + // 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/14041018/Documents/BKP/x-saherelm.x-poi.drawer.class copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-poi.drawer.class copy.mq5 new file mode 100644 index 0000000..21fbd78 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.x-poi.drawer.class copy.mq5 @@ -0,0 +1,1195 @@ +/////////////////////////////////////////////////////// +// +// 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-pivot.analysis.lib.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; + } + + // + // Drawers ... + + /** + * Dar Specified Pivot ... + * + * @param pivot: XPivot, Specified Pivot ... + * @param object: XCBarArrowObject, pointer reference for Drawn Object ... + * @param peakArrow: int, Specified Arrow Code for Peak Pivots ... + * @param valeArrow: int, Specified Arrow Code for Vale Pivots ... + * @param threshold: int, distance between price and arrow in Point ... + * + * @return ( bool ) + */ + bool DrawPivot( + XPivot &pivot, + XCBarArrowObject *&object, + int peakArrow = 159, + int valeArrow = 159, + int threshold = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Normalize ... + threshold = NormalizeInt(threshold, 5); + peakArrow = NormalizeInt(peakArrow, 159); + valeArrow = NormalizeInt(valeArrow, 159); + + // + // Validate ... + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + // Get Pivot's Bar ... + XOHCL bar; + result = pivot.GetBar(bar); + if (!result) + { + return result; + } + + // + int arrow = pivot.IsPeak() + ? peakArrow + : valeArrow; + string name = pivot.GetObjectID(); + ENUM_X_PRICE type = pivot.IsPeak() + ? X_PRICE_HIGH + : X_PRICE_LOW; + XPOIStyle style = pivot.IsPeak() + ? defaultBullishStyle + : defaultBearishStyle; + ENUM_ARROW_ANCHOR anchor = pivot.IsPeak() + ? ANCHOR_BOTTOM + : ANCHOR_TOP; + object = new XCBarArrowObject(); + result = object.CreateByBar( + ChartIdentification(), + name, + SubWindowIdentification(), + arrow, + bar, + type, + threshold // + ); + if (result) + { + // + // Apply Styles ... + object.ArrowAnchor(anchor); + ApplyBarArrowStyle( + object, + style // + ); + } + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; + } + + /** + * Draw Specified Box ... + * + * @param object: XCBoxObject, pointer reference for Drawn Object ... + * @param name: Box Name ... + * @param upper: double, Box Upper ... + * @param lower: double, Box Lower ... + * @param from: datetime, From Time ... + * @param to: datetime, To Time ... + * @param at: datetime, Specified At Time ... + * + * @return ( bool ) + */ + bool DrawBox( + XCBoxObject *&object, + string name, + double upper, + double lower, + datetime from, + datetime to, + datetime at // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Normalize ... + to = NormalizeTime(to); + from = NormalizeTime(from); + + // + // Validate ... + result = + upper > 0 && + lower > 0 && + to > from && + IsSpecifiedValid(to) && + IsSpecifiedValid(name) && + IsSpecifiedValid(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 // + ); + + // + return result; + } + + /** + * Draw Specific Box ... + * + * @param box: XBoxZone, Specified Box ... + * @param object: XCBarArrowObject, pointer reference for Drawn Object ... + * @param ignoreAt: bool, Ignore Box at or not ... + * + * @return ( bool ) + */ + bool DrawBox( + XBoxZone &box, + XCBoxObject *&object, + bool ignoreAt = true // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Validate ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + datetime at = box.at; + if (ignoreAt) + { + at = NULL; + } + + // + string name = box.GetTag(); + result = DrawBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + at // + ); + if (result) + { + // + // Apply Style ... + XPOIStyle style; + GetBoxStyle( + style, + box.dir // + ); + + // + ApplyBoxStyle( + object, + style // + ); + + // + style.Clean(); + } + + // + return result; + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal, Specified Signal ... + * @param object: XCSignalObject, pointer reference for Drawn Object ... + * @param length: int, Signal Length ... + */ + 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 Specified Trend Line ... + * + * @param fromPrice: double, from Price ... + * @param fromTime: datetime, from Time ... + * @param toPrice: double, to Price ... + * @param toTime: datetime, to Time ... + * @param object: CChartObjectTrend, pointer reference for Drawn Object ... + * @param name: Object Name ... + * @param rayRight: bool, ray to Right ... + * @param rayLeft: boo, ray to Left ... + * + * @return ( bool ) + */ + bool DrawTrendLine( + double fromPrice, + datetime fromTime, + double toPrice, + datetime toTime, + CChartObjectTrend *&object, + string name, + bool rayRight = false, + bool rayLeft = false // + ) + { + // + bool result = false; + + // + // Prepare ... + object = new CChartObjectTrend(); + + // + // Validate ... + result = + toPrice > 0 && + fromPrice > 0 && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime) && + toTime > fromTime; + if (!result) + { + return result; + } + + // + // Create Object ... + result = object.Create( + ChartIdentification(), + name, + SubWindowIdentification(), + fromTime, + fromPrice, + toTime, + toPrice // + ); + if (result) + { + // + ENUM_X_DIRECTION dir = + fromPrice < toPrice + ? X_DIRECTION_BULLISH + : fromPrice > toPrice + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + ApplyTrendLineStyle( + object, + dir // + ); + + // + object.RayLeft(rayLeft); + object.RayRight(rayRight); + } + + // + return result; + } + + /** + * Draw Trend Line based on Swings Points ... + * + * @param swings: XOHCL, Specified Swings ... + * @param dir: ENUM_X_DIRECTION, Specified Trend Direction ... + * @param object: CChartObjectTrend, pointer reference for Drawn Object ... + * @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) + { + // + ApplyTrendLineStyle( + object, + dir // + ); + + // + object.RayLeft(rayLeft); + object.RayRight(rayRight); + } + + // + return result; + } + + /** + * Draw Pivot Analysis ... + * + * @param analysis: XPivotAnalysis, referece Specified Pivot Analysis ... + * + * @return ( bool ) + */ + bool DrawXPivotAnalysis( + XPivotAnalysis &analysis, + XCPivotAnalysisObject *&object // + ) + { + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Normalize ... + + // + // Validate ... + result = analysis.IsValid() && + analysis.IsAnalysed(); + if (!result) + { + return result; + } + + // + object = new XCPivotAnalysisObject(); + result = object.Create( + ChartIdentification(), + SubWindowIdentification(), + analysis // + ); + if (result) + { + // + ApplyPivotAnalysisStyle( + object, + analysis // + ); + } + + // + return result; + } + + // + // Stylers ... + + /** + * Get Specified Style for Specified Direction ... + * + * @param style: XPOIStyle, reference to hold result ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void GetStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + // Prepare ... + style.Clean(); + + // + // Validate ... + if (!HasDirection(forDir)) + { + return; + } + + // + if (IsSpecifiedBullish(forDir)) + { + style = defaultBullishStyle; + } + else + { + style = defaultBearishStyle; + } + } + + /** + * Get Specified Box Style for Specified Direction ... + * + * @param style: XPOIStyle, reference to hold result ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void GetBoxStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + // Prepare ... + style.Clean(); + + // + // Validate ... + if (!HasDirection(forDir)) + { + return; + } + + // + if (IsSpecifiedBullish(forDir)) + { + style = boxBullishStyle; + } + else + { + style = boxBearishStyle; + } + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: XCBoxObject, pointer reference of Object ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyBoxStyle( + XCBoxObject *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.BoxFill(style.fill); + object.BoxColor(style.clr); + object.BoxWidth(style.width); + object.BoxStyle(style.style); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: XCBarArrowObject, pointer reference of Object ... + * @param style: XPOIStyle, Specifed Style to Apply ... + */ + void ApplyBarArrowStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObject, pointer reference of Object ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + */ + void ApplyTrendLineStyle( + CChartObjectTrend *&object, + ENUM_X_DIRECTION forDir // + ) + { + // + bool has = object != NULL; + if (!has) + { + return; + } + + // + if (!HasDirection(forDir)) + { + return; + } + + // + XPOIStyle style; + GetStyle(style, forDir); + + // + object.Color(style.clr); + object.Style(style.style); + object.Width(style.width); + + // + style.Clean(); + } + + /** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObject, pointer reference of Object ... + * @param model: XPivotAnalysis, referece to access requirements ... + */ + void ApplyPivotAnalysisStyle( + XCPivotAnalysisObject *&object, + XPivotAnalysis &model // + ) + { + // + // Validate ... + bool has = model.IsValid() && + model.IsAnalysed() && + object != NULL; + if (!has) + { + return; + } + + // + XPOIStyle style; + + // + // Support ... + style = defaultBullishStyle; + object.SupportColor(style.clr); + object.SupportWidth(style.width); + object.SupportStyle(style.style); + + // + // Resistance ... + style = defaultBearishStyle; + object.ResistanceColor(style.clr); + object.ResistanceWidth(style.width); + object.ResistanceStyle(style.style); + + // + // Upper ... + if (model.IsPeakAnalysed()) + { + // + GetStyle( + style, + model.peakDir // + ); + if (!HasDirection(model.peakDir)) + { + // + style.Default(); + style.clr = clrGray; + } + + // + object.UpperColor(style.clr); + object.UpperWidth(style.width); + object.UpperStyle(style.style); + object.UpperRayLeft(false); + object.UpperRayRight(true); + } + + // + // Lower ... + if (model.IsValeAnalysed()) + { + // + GetStyle( + style, + model.valeDir // + ); + if (!HasDirection(model.valeDir)) + { + // + style.Default(); + style.clr = clrGray; + } + + // + object.LowerColor(style.clr); + object.LowerWidth(style.width); + object.LowerStyle(style.style); + object.UpperRayLeft(false); + object.LowerRayRight(true); + } + + // + style.Clean(); + } + + // + 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/14041018/Documents/BKP/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..51e7c7c --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..abde4f0 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/x-saherelm.x-poi.state.lib.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x-poi.state.lib.mq5 new file mode 100644 index 0000000..e52ea2b --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/BKP/x-saherelm.x121.xcatb.v1.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x121.xcatb.v1.mq5 new file mode 100644 index 0000000..70f72ec --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.x121.xcatb.v1.mq5 @@ -0,0 +1,5499 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 new file mode 100644 index 0000000..0d4dcab --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 @@ -0,0 +1,1184 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121XKISignaller ... +// Description: X121XKI 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 X121XKI Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.x121.xki.helper.mq5" +#include "../Classes/x-saherelm.x121.xki.parser.class.mq5" +#include "../Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base X121XKI base Signaller ... +class XCX121XKIBaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + X121XKIInputs kiInputs; // X121XKI Inputs ... + XCX121XKIHelper *kiHelper; // X121XKI Indicator Helper ... + XCX121XKIPOIDrawer *poiDrawer; // X121XKI POI Drawer ... + XCX121XKIPOIDetector *poiDetector; // X121XKI POI Detector ... + XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ... + + // + // Constructor ... + XCX121XKIBaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + X121XKIInputs &_kiInputs, // X121XKIInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating X121XKI Indicator Helper Class ... + if (_kiInputs.IsValid()) + { + // + kiHelper = new XCX121XKIHelper(); + bool isInited = kiHelper.Init( + _symbol, + _period, + _kiInputs // + ); + if (isInited) + { + kiInputs = _kiInputs; + } + else + { + // + delete kiHelper; + ZeroMemory(kiHelper); + } + } + + // + // Instantiate X121XKI Helper Parser ... + kiParser = new XCX121XKIHelperParser(kiHelper); + + // + poiDrawer = new XCX121XKIPOIDrawer(); + poiDetector = new XCX121XKIPOIDetector(kiHelper, kiParser); + } + + // + // Deconstructor ... + ~XCX121XKIBaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + kiInputs.Clean(); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + delete kiHelper; + ZeroMemory(kiHelper); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = kiInputs.IsValid() && + kiHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// X121XKI Strategy 1 Signaller Class ... +class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCX121XKIStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + X121XKIInputs &_kiInputs, // X121XKIInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCX121XKIBaseSignaller("X121XKI1", + _symbol, + _period, + _kiInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + } + + // + // Deconstructor ... + ~XCX121XKIStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = true; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = false; + bool useSignaller5 = false; + + // + XBoxZone tmpZone; + string provider = NULL; + ENUM_X_DIRECTION tmpDir; + + // + bool signaller1HasSignal = false; + bool signaller2HasSignal = false; + bool signaller3HasSignal = false; + bool signaller4HasSignal = false; + bool signaller5HasSignal = false; + + // + // Validator Flags ... + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + + // + // Signal Checking ... + + // + // Signal Detection Flags ... + + // + // Signaller 1 ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += "1"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + if (useSignaller2) + { + // + signaller2HasSignal = Strategy2HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller2HasSignal) + { + // + provider += "2"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + if (useSignaller3) + { + // + signaller3HasSignal = Strategy3HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller3HasSignal) + { + // + provider += "3"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + if (useSignaller4) + { + // + signaller4HasSignal = Strategy4HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller4HasSignal) + { + // + provider += "4"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 5 ... + if (useSignaller5) + { + // + signaller5HasSignal = Strategy5HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller5HasSignal) + { + // + provider += "5"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal || + signaller5HasSignal; + + // + // Signal Validating ... + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Other Drawing Materials ... + XPOIDrawConfig drawConfig; + drawConfig.Default(); + + // + poiDrawer.DrawZone(zone, drawConfig); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + tmpZone.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * Pattern‑based reversal: + * - Detects Pin Bar or Signal Key Bar. + * - Confirms with POI detector. + * - Good for reversals at support/resistance. + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = poiDetector.IsBullishPOI(bar.Index()); + bool isBearish = poiDetector.IsBearishPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_SIGNALKEY); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * Trend‑following: + * - Requires KI Fast + KI Slow alignment. + * - Confirms with MA crossover. + * - RSI filter to avoid false signals. + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = kiParser.IsBullishMomentumTrend(bar.Index()); + bool isBearish = kiParser.IsBearishMomentumTrend(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_MOMENTUM); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Breakout: + * - Detects price breaking KI bands with ATR confirmation. + * - Confirms with Momentum Bar pattern. + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = poiDetector.IsBullishBreakoutPOI(bar.Index()); + bool isBearish = poiDetector.IsBearishBreakoutPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_TRUE_GAPED); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Exhaustion: + * - Strong trend + RSI extreme + volatility low. + * - Confirms with Piercing/Dark Cloud Cover candlestick. + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = poiDetector.IsBullishTrendExhaustedPOI(bar.Index()); + bool isBearish = poiDetector.IsBearishTrendExhaustedPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_PIERCING); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + + /** + * Check Bar Has Signal Based on Strategy 5 ... + * + * Continuation: + * - Requires strong trend confirmation (KI fast/slow + MA crossover + RSI filter). + * - Confirms with continuation candlestick patterns (Flag or Rising pattern). + * - Ensures zone validity for entry. + * + * @return ( bool ) + */ + bool Strategy5HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = kiParser.IsTrendStrongBullish(bar.Index()); + bool isBearish = kiParser.IsTrendStrongBearish(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Confirm Direction by Candlestick Continuation Patterns ... + isBullish = + isBullish && + poiDetector.IsBullishContinuationPOI(bar.Index()); + isBearish = + isBearish && + poiDetector.IsBearishContinuationPOI(bar.Index()); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = ToBox(bar, zone, dir, X_BAR_PATTERN_PIERCING); + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.backtester.ea copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.backtester.ea copy.mq5 new file mode 100644 index 0000000..a2ff4f5 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.backtester.ea copy.mq5 @@ -0,0 +1,1899 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../XFIMAEA/Classes/x-saherelm.xfima.signaller.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 + +// +// Configurations ... +input group "Configuration"; +input bool eaProcessAllTicks = false; // Process All Ticks +input double eaSignallerR2R = 2.0; // Risk To Reward Ratio +input double eaSignallerVolume = 0.01; // Default Volume +input double eaSignallerRiskInPoint = 50; // Default Risk In Point + +// +// 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 fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Middle Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 int maBandLength = 7; // MA Band Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + +// +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 showHK = true; // Show HK +input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showMABand = true; // Show MA Band +input bool showBarTime = true; // Show Bar Time +input bool showZigZag = true; // Show ZigZag +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 + +// +// Define Local Variables ... + +// +// Requirements ... +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Registered Signallers ... +XCXFIMAStrategy1Signaller *fima1Signaller; // XFIMA1 Signaller ... + +// +XFIMAMarketStructure marketStructure; // POI Analysis Result ... +XFIMAPatternDetectorConfig detectorConfig; // POI Detector Config ... +XFIMAMarketStructureDrawerConfig marketStructureDrawerConfig; // POI Drawer Config ... + +// +// Drawer and eaDraws ... +CArrayObj eaDraws; // Drawn Objects ... +CArrayObj *marketStructureObjects; // Market Structure Objects ... + +// +XBarTracker eaBarTracker; // EA Bar Traker ... + +// +// Registered Handlers ... +int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... + +// +bool eaIsNewBar; // Check New Bar ... + +// +// 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.allowedTPSLStep = 10; + eaExpert.minAllowedRiskInPoint = 20; + eaExpert.volume = eaSignallerVolume; + eaExpert.riskToRewardRatio = eaSignallerR2R; + eaExpert.riskInPoint = eaSignallerRiskInPoint; + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Here Instantiate Signaller Class ... + + // + // Preparing Indicator Inputs ... + XFIMAInputs fimaInputs; + + // + // This is Default Configuration ... + fimaInputs.Default(); + fimaInputs.Hide(); + + // + // Here we Attach Inputs to Indicator ... + fimaInputs.scMethod = scMethod; + fimaInputs.scPeriod = scPeriod; + fimaInputs.mcMethod = mcMethod; + fimaInputs.mcPeriod = mcPeriod; + fimaInputs.lcMethod = lcMethod; + fimaInputs.lcPeriod = lcPeriod; + fimaInputs.hcMethod = hcMethod; + fimaInputs.hcPeriod = hcPeriod; + fimaInputs.upperMode = upperMode; + fimaInputs.lowerMode = lowerMode; + fimaInputs.fiboUpperZoneLevel = fiboUpperZoneLevel; + fimaInputs.fiboMiddleZoneLevel = fiboMiddleZoneLevel; + fimaInputs.fiboLowerZoneLevel = fiboLowerZoneLevel; + fimaInputs.sarStep = sarStep; + fimaInputs.sarMax = sarMax; + fimaInputs.maMethod = maMethod; + fimaInputs.maAppliedTo = maAppliedTo; + fimaInputs.maFastLength = maFastLength; + fimaInputs.maSlowLength = maSlowLength; + fimaInputs.maBandLength = maBandLength; + fimaInputs.zigzagDepth = zigzagDepth; + fimaInputs.zigzagDeviation = zigzagDeviation; + fimaInputs.zigzagBackStep = zigzagBackStep; + fimaInputs.zigzagUppersMode = zigzagUppersMode; + fimaInputs.zigzagLowersMode = zigzagLowersMode; + fimaInputs.showPV = showPV; + fimaInputs.showHK = showHK; + fimaInputs.showSAR = showSAR; + fimaInputs.showMAFast = showMAFast; + fimaInputs.showMASlow = showMASlow; + fimaInputs.showMABand = showMABand; + fimaInputs.showZigZag = showZigZag; + fimaInputs.showFiboZone = showFiboZone; + fimaInputs.startCalculationForLastBars = startCalculationForLastBars; + fimaInputs.sarArrowCode = sarArrowCode; + fimaInputs.peakArrowCode = peakArrowCode; + fimaInputs.valeArrowCode = valeArrowCode; + + // + // Instantiate Signaller ... + + // + // XFIMA1 Signaller ... + fima1Signaller = new XCXFIMAStrategy1Signaller( + _Symbol, + _Period, + fimaInputs, + eaProcessAllTicks, // Process All Ticks ... + eaSignallerR2R, // Signaller Risk to Reward Ratio ... + eaSignallerRiskInPoint, // Default Risk In Points ... + eaSignallerVolume // Defaul Volume ... + ); + fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); + + // + isInited = + fima1Signaller.IsValid(); + 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; + } + + // + // Configure XFIMA POI Detector / Drawer ... + detectorConfig.Default(); + detectorConfig.FullDetect(); + marketStructureDrawerConfig.FullDraw(); + + // + 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(eaCTHandler); + + // + eaBarTracker.Clean(); + + // + delete fima1Signaller; + ZeroMemory(fima1Signaller); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + eaIsNewBar = eaBarTracker.IsNewBar(); + bool canProcess = eaProcessAllTicks + ? true + : eaIsNewBar; + // + eaExpert.HandleOnTick(); + + // + if (!canProcess) + { + return; + } + + // + // Bar Index ... + int barIndex = 1; + + // + fima1Signaller.OnTick(barIndex); + + // + // AnalyseMarket(barIndex); +} + +// +// 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)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ); + 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(); +} + +/** + * Trigger OnSignal Event ... + * + * @param signal: XSignal + */ +void OnSignalTriggered(XSignal &signal) +{ + // + // Validate Signal ... + if (!signal.IsValid()) + { + return; + } + + // + // TODO: Fix this ... + // return; + + // + // Draw Signal on Chart ... + XCSignalObject *iSignalObj; + bool has = fima1Signaller.poiDrawer.DrawSignal( + signal, + iSignalObj, + 7 // + ); + + // + if (has) + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT result; + eaExpert.eaTrader.ExecuteSignal( + signal, + result // + ); + + // + Print("Signal Issued: ", signal.GetObjectID()); + } + + // + // Try to Execute Signal ... + + // + // Draw Signal Vertical Line ... + + // // + // CChartObjectVLine *iObj = new CChartObjectVLine(); + + // // + // string iName = signal.GetObjectID(); + // color iColor = IsLong(signal.type) ? clrLime : clrRed; + + // // + // bool has = iObj.Create( + // fima2Signaller.poiDrawer.ChartIdentification(), + // iName, + // fima2Signaller.poiDrawer.SubWindowIdentification(), + // signal.time // + // ); + // if (has) + // { + // // + // iObj.Width(2); + // iObj.Color(iColor); + + // // + // // eaDraws.Add(iObj); + // } + + // // + // // Alert Issued Signal ... + // string message = signal.GetMessage(); + + // + // int signalBarIndex = GetBarIndex( + // signal.symbol, + // signal.period, + // signal.time // + // ); + // AnalyseMarket(signalBarIndex); +} + +// +// 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); +} + +// +void AnalyseMarket(int barIndex = 0) +{ + // + bool has = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + string symbol = fima1Signaller.symbol; + ENUM_TIMEFRAMES period = fima1Signaller.period; + + // + // Retrieve Signal Bar ... + XOHCL bar; + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // TODO: Remove this and add in OnInit() Method ... + + // + // Configuring Detector ... + + // + detectorConfig.detectOB = true; + detectorConfig.detectFVG = true; + + // + detectorConfig.detectSupport = true; + detectorConfig.detectResistance = true; + detectorConfig.detectSwingTrend = true; + + // + detectorConfig.detectPinned = true; + detectorConfig.detectMomentum = true; + detectorConfig.detectEngulfed = true; + detectorConfig.detectTrueGaped = true; + + // + detectorConfig.detectStarPattern = true; + detectorConfig.detectFlagPattern = true; + detectorConfig.detectRisingPattern = true; + detectorConfig.detectPiercingPattern = true; + detectorConfig.detectSignalKeyBarPattern = true; + + // + detectorConfig.analyseFIMAPVPivots = true; + detectorConfig.analyseFIMASARPivots = false; + detectorConfig.analyseFIMAZigZagPivots = true; + + // + // Configure Drawer ... + + // + marketStructureDrawerConfig.drawOB = false; + marketStructureDrawerConfig.drawFVG = false; + + // + marketStructureDrawerConfig.drawPinned = false; + marketStructureDrawerConfig.drawEngulfed = true; + marketStructureDrawerConfig.drawTrueGaped = false; + marketStructureDrawerConfig.drawMomentum = false; + marketStructureDrawerConfig.drawFlagPattern = false; + marketStructureDrawerConfig.drawStarPattern = false; + marketStructureDrawerConfig.drawRisingPattern = false; + marketStructureDrawerConfig.drawPiercingPattern = false; + marketStructureDrawerConfig.drawSignalKeyBarPattern = true; + + // + // Recents ... + marketStructureDrawerConfig.drawRecentPatterns = false; + marketStructureDrawerConfig.drawFakeBreakedZone = false; + marketStructureDrawerConfig.drawRecentlyTestedZones = false; + marketStructureDrawerConfig.drawRecentlyBreakedZones = false; + + // + // XPV ... + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysis = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisZones = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisTrends = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisPivots = true; + + // + // XSAR ... + marketStructureDrawerConfig.drawFIMASARPivotsAnalysis = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisZones = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisTrends = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisPivots = false; + + // + // XZigZag ... + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysis = true; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisZones = true; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisTrends = false; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisPivots = false; + + // + // Analyse Market on Signalling Bar ... + fima1Signaller.poiDetector.AnalyseMarket( + bar, + marketStructure, + detectorConfig // + ); + + // + XFIMASIgballer2First(bar); + // HandleLookupSignal(bar); + + // + bar.Clean(); +} + +// +// Handle Signal Looking Up ... +// Register it as XFIMA Signaller 2 ... +void XFIMASIgballer2First(XOHCL &bar) +{ + // + bool has = + bar.IsValid(); + if (!has) + { + return; + } + + // + XBoxZone iZone; + XSignal iSignal; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + int barIndex = bar.Index(); + double iPrice = EMPTY_VALUE; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(marketStructure.pinnedDir); + bool hasEngulfedBar = HasDirection(marketStructure.engulfedDir); + bool hasFlagPattern = HasDirection(marketStructure.flagPatternDir); + bool hasStarPattern = HasDirection(marketStructure.starPatternDir); + bool hasRisingPattern = HasDirection(marketStructure.risingPatternDir); + bool hasPiercingPattern = HasDirection(marketStructure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(marketStructure.signalKeyBarPatternDir); + + // + // PV Trend Line ... + string pvTrendName = "XPVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + // ZigZag Trend Line ... + string zgTrendName = "XZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Check PV Analysis ... + bool hasPVAnalysis = marketStructure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + XCBoxObject *iSupportObj; + has = marketStructure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + has = fima2Signaller.poiDrawer.DrawBox( + supportBox, + iSupportObj, + true, // Ignore At ... + supportBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + fima2Signaller.poiDrawer.GetBoxStyle( + iStyle, + supportBox.dir // + ); + fima2Signaller.poiDrawer.ApplyBoxStyle( + iSupportObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Resistance ... + XBoxZone resistanceBox; + XCBoxObject *iResistanceObj; + has = marketStructure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + has = fima2Signaller.poiDrawer.DrawBox( + resistanceBox, + iResistanceObj, + true, // Ignore At ... + resistanceBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + fima2Signaller.poiDrawer.GetBoxStyle( + iStyle, + resistanceBox.dir // + ); + fima2Signaller.poiDrawer.ApplyBoxStyle( + iResistanceObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Pivots ... + XPivot pivots[]; + int pivotsCount = fima2Signaller.poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(pivotsCount); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = fima2Signaller.poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + pivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Check ZigZag Analysis ... + bool hasZGAnalysis = marketStructure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + XCBoxObject *iSupportObj; + has = marketStructure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + has = fima2Signaller.poiDrawer.DrawBox( + supportBox, + iSupportObj, + true, // Ignore At ... + supportBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + fima2Signaller.poiDrawer.GetBoxStyle( + iStyle, + supportBox.dir // + ); + fima2Signaller.poiDrawer.ApplyBoxStyle( + iSupportObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Resistance ... + XBoxZone resistanceBox; + XCBoxObject *iResistanceObj; + has = marketStructure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + has = fima2Signaller.poiDrawer.DrawBox( + resistanceBox, + iResistanceObj, + true, // Ignore At ... + resistanceBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + fima2Signaller.poiDrawer.GetBoxStyle( + iStyle, + resistanceBox.dir // + ); + fima2Signaller.poiDrawer.ApplyBoxStyle( + iResistanceObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Pivots ... + XPivot pivots[]; + int pivotsCount = fima2Signaller.poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(pivotsCount); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = fima2Signaller.poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + pivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = marketStructure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + marketStructure.support, + supports // + ); + + // + XCBoxObject *iObj; + has = fima2Signaller.poiDrawer.DrawBox( + marketStructure.support, + iObj); + if (has) + { + } + } + + // + // Resistance ... + bool hasResistance = marketStructure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + marketStructure.resistance, + resistances // + ); + + // + XCBoxObject *iObj; + has = fima2Signaller.poiDrawer.DrawBox( + marketStructure.resistance, + iObj); + if (has) + { + } + } + + // + // Check Bar Pattern Exists ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + + // + // Select Pattern Direction and Price and Price Type ... + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = marketStructure.pinnedDir; + iName = "pinned" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = marketStructure.engulfedDir; + iName = "engulfed" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = marketStructure.flagPatternDir; + iName = "flagPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = marketStructure.starPatternDir; + iName = "starPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = marketStructure.risingPatternDir; + iName = "risingPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = marketStructure.piercingPatternDir; + iName = "piercingPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = marketStructure.signalKeyBarPatternDir; + iName = "signalKeyBarPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + iPrice = bar.GetPrice(iPriceType); + + // + has = HasDirection(iDir); + } + + // + // Validate Patterns based on MA Band ... + if (has) + { + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fima2Signaller.fimaHelper.GetMABandUpper(barIndex); + double iMABandLower = fima2Signaller.fimaHelper.GetMABandLower(barIndex); + + // + // Validate ... + has = isBullish + ? iPrice < iMABandLower + : iPrice > iMABandUpper; + } + + // + // Select a Zone which Price inside it ... + + // + // Validate Happens in Zone ... + int insideZoneIDX = -1; + has = has && + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + + // + // Validate Selected Inside Zone ... + // whith Bars Edge ... + has = IsValidIndex(insideZoneIDX); + if (has) + { + // + if (isBullish) + { + iZone = supports[insideZoneIDX]; + } + else + { + iZone = resistances[insideZoneIDX]; + } + + // + has = isBullish + ? bar.high > supports[insideZoneIDX].upper + : bar.low < resistances[insideZoneIDX].lower; + } + + // + // Checking Liquidities ... + + // + // Draw Selected and Validated Bar and Selected Zone ... + if (has) + { + // + int iWidth = 1; + int iCode = 159; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBoxObject *iZoneObj; + XCBarArrowObject *iPatternObj; + + // + has = fima2Signaller.poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + if (has) + { + } + + // + has = fima2Signaller.poiDrawer.DrawBox( + iZone, + iZoneObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + fima2Signaller.poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + iStyle.width = 2; + iStyle.clr = iClr; + fima2Signaller.poiDrawer.ApplyBoxStyle( + iZoneObj, + iStyle // + ); + } + } + + // + // Preparing Signal ... + if (has) + { + // + iSignal.time = bar.time; + iSignal.provider = "XFima"; + iSignal.symbol = bar.symbol; + iSignal.period = bar.period; + iSignal.mode = X_ORDER_MODE_MARKET; + iSignal.entry = GetEntry(bar.symbol, iDir); + iSignal.type = isBullish + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + iSignal.volume = 0.01; + + // + double _r2r = 2.0; + double _slDistanceInPoint = 5; + double _point = GetPoints(iSignal.symbol); + double _riskDistance = _slDistanceInPoint * _point; + double _risk = _riskDistance + MathAbs((isBullish ? iZone.lower : iZone.upper) - iSignal.entry); + double _reward = GetSpread(iSignal.symbol) + (_risk * _r2r); + + // + double sl = isBullish + ? iSignal.entry - _risk + : iSignal.entry + _risk; + double tp = isBullish + ? iSignal.entry + _reward + : iSignal.entry - _reward; + + // + iSignal.sl = sl; + iSignal.tp = tp; + + // + has = iSignal.IsValid(); + if (has) + { + // + XCSignalObject *iSignalObj; + has = fima2Signaller.poiDrawer.DrawSignal( + iSignal, + iSignalObj, + 7 // + ); + } + } + + // + // For Logging ... + if (has) + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT eResult; + has = eaExpert.eaTrader.ExecuteSignal(iSignal, eResult); + Print("Detect a Potential Place for Price Movement: ", ToXString(iDir), ", Time: ", bar.time); + } + + // + // Cleanup Resources ... + iZone.Clean(); + iSignal.Clean(); + SpecifiedClean(supports); + SpecifiedClean(resistances); +} + +// +void HandleLookupSignal(XOHCL &bar) +{ + // + bool has = + bar.IsValid(); + if (!has) + { + return; + } + + // + XBoxZone iZone; + XSignal iSignal; + string iName = NULL; + bool isBullish = false; + bool isBearish = false; + int barIndex = bar.Index(); + double iPrice = EMPTY_VALUE; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + int cIDX = 0; + int pIDX = cIDX + 1; + + // + // Check for a Cross ... + + // + // fima2Signaller.fimaHelper.Update(barIndex); + has = fima2Signaller.fimaHelper.GetConditions( + fimaConditions, + barIndex, + 5 // + ); + + // + double cSlowMA = fimaConditions.maSlowBuffer[cIDX]; + double pSlowMA = fimaConditions.maSlowBuffer[pIDX]; + + // + double cMAUpper = fimaConditions.maBandUpperBuffer[cIDX]; + double cMALower = fimaConditions.maBandLowerBuffer[cIDX]; + + // + double pMAUpper = fimaConditions.maBandUpperBuffer[pIDX]; + double pMALower = fimaConditions.maBandLowerBuffer[pIDX]; + + // + bool isCrossedOver = cSlowMA > cMALower && + pSlowMA < pMALower; + + // + bool isCrossedUnder = cSlowMA < cMAUpper && + cSlowMA > pMAUpper; + + // + has = isCrossedOver || + isCrossedUnder; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + + // + if (has) + { + // + isBullish = isCrossedOver; + isBearish = isCrossedUnder; + } + + // + iDir = (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (has) + { + Print("Conditions Detected ..."); + } + + // + // Cleanup Resources ... + fimaConditions.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.backtester.ea.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.backtester.ea.mq5 new file mode 100644 index 0000000..41328ec --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.backtester.ea.mq5 @@ -0,0 +1,1053 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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 fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Middle Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + +// +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 showZigZag = true; // Show ZigZag +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 + +// +// 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.xfima", + "", // Calculation ... + scMethod, + scPeriod, + mcMethod, + mcPeriod, + lcMethod, + lcPeriod, + hcMethod, + hcPeriod, + upperMode, + lowerMode, + fiboUpperZoneLevel, + fiboMiddleZoneLevel, + fiboLowerZoneLevel, + sarStep, + sarMax, + maMethod, + maAppliedTo, + maFastLength, + maSlowLength, + zigzagDepth, + zigzagDeviation, + zigzagBackStep, + zigzagUppersMode, + zigzagLowersMode, + "", // Presentation ... + showPV, + showSAR, + showMAFast, + showMASlow, + showZigZag, + 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)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ); + 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/14041018/Documents/BKP/x-saherelm.xfima.helper copy 2.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper copy 2.mq5 new file mode 100644 index 0000000..a175d65 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper copy 2.mq5 @@ -0,0 +1,8413 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXFIMAHelper +// 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 "../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_XFIMA_BUFFERS +{ + // + // Plot Buffers ... + XFIMA_MA_FAST_LINE = 0, + XFIMA_MA_FAST_COLOR_LINE = 1, + XFIMA_MA_SLOW_LINE = 2, + XFIMA_MA_SLOW_COLOR_LINE = 3, + XFIMA_SAR_LINE = 4, + XFIMA_SAR_COLOR_LINE = 5, + XFIMA_PEAK_LINE = 6, + XFIMA_VALE_LINE = 7, + XFIMA_FIBO_UPPER_LINE = 8, + XFIMA_FIBO_MIDDLE_LINE = 9, + XFIMA_FIBO_LOWER_LINE = 10, + XFIMA_ZIGZAG_LINE = 11, + XFIMA_MA_BAND_UPPER_LINE = 12, + XFIMA_MA_BAND_LOWER_LINE = 13, + XFIMA_HK_OPEN_LINE = 14, + XFIMA_HK_HIGH_LINE = 15, + XFIMA_HK_LOW_LINE = 16, + XFIMA_HK_CLOSE_LINE = 17, + XFIMA_HK_COLOR_LINE = 18, + XFIMA_HK_BAND_UPPER_LINE = 19, + XFIMA_HK_BAND_LOWER_LINE = 20, + XFIMA_PB_BAND_UPPER_LINE = 21, + XFIMA_PB_BAND_LOWER_LINE = 22, + XFIMA_ATR_BAND_UPPER_LINE = 23, + XFIMA_ATR_BAND_LOWER_LINE = 24, + // + // Data Buffers ... + XFIMA_MA_FAST_STATE_LINE = 25, + XFIMA_MA_SLOW_STATE_LINE = 26, + XFIMA_SAR_STATE_LINE = 27, + XFIMA_SC_HH_LINE = 28, + XFIMA_SC_LL_LINE = 29, + XFIMA_MC_HH_LINE = 30, + XFIMA_MC_LL_LINE = 31, + XFIMA_LC_HH_LINE = 32, + XFIMA_LC_LL_LINE = 33, + XFIMA_HC_HH_LINE = 34, + XFIMA_HC_LL_LINE = 35, + XFIMA_ZIGZAG_HIGHS_LINE = 36, + XFIMA_ZIGZAG_HIGHS_TIME_LINE = 37, + XFIMA_ZIGZAG_LOWS_LINE = 38, + XFIMA_ZIGZAG_LOWS_TIME_LINE = 39, + XFIMA_HK_RAW_OPEN_LINE = 40, + XFIMA_HK_RAW_HIGH_LINE = 41, + XFIMA_HK_RAW_LOW_LINE = 42, + XFIMA_HK_RAW_CLOSE_LINE = 43, + XFIMA_PB_BAND_RAW_UPPER_LINE = 44, + XFIMA_PB_BAND_RAW_LOWER_LINE = 45, + XFIMA_ATR_LINE = 46, + XFIMA_ATR_BAND_RAW_UPPER_LINE = 47, + XFIMA_ATR_BAND_RAW_LOWER_LINE = 48, +}; + +// +// Input Models ... +struct XFIMAInputs +{ + // + // 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 fiboUpperZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboLowerZoneLevel; // 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 + int maBandLength; // MA Band Length + int zigzagDepth; // ZigZag Depth + int zigzagDeviation; // ZigZag Deviation + int zigzagBackStep; // ZigZag Back Step + ENUM_X_PRICE zigzagUppersMode; // ZigZag High Detect Mode + ENUM_X_PRICE zigzagLowersMode; // ZigZag Low Detect Mode + bool hkIgnoreShadows; // HK Remove noises + int hkSmoothingLength; // HK Smoothing Length + ENUM_X_MA_METHOD hkSmoothingMode; // HK Smoothing Method + int atrLength; // ATR Length + double atrMultiplier; // ATR Band Multiplier + int atrSmoothingLength; // ATR Smoothing Length + ENUM_X_PRICE atrUpperPriceType; // ATR Upper Zone Applied To + ENUM_X_PRICE atrLowerPriceType; // ATR Lower Zone Applied To + ENUM_X_MA_METHOD atrSmoothingMode; // ATR Smoothing Method + + // + // Presentation ... + bool showPV; // Show PV + bool showHK; // Show HK + bool showSAR; // Show Sar + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow + bool showMABand; // Show MA Band + bool showHKBand; // Show HK Band + bool showATRBand; // Show ATR Band + bool showZigZag; // Show ZigZag + 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) ... + XFIMAInputs() + { + 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 + fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level + fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level + fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 + maBandLength = 7; // MA Band Length + zigzagDepth = 12; // ZigZag Depth + zigzagDeviation = 5; // ZigZag Deviation + zigzagBackStep = 3; // ZigZag Back Step + zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode + zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + hkIgnoreShadows = true; // HK Remove noises + hkSmoothingLength = 21; // HK Smoothing Length + hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method + atrLength = 14; // ATR Length + atrMultiplier = 1.5; // ATR Band Multiplier + atrSmoothingLength = 21; // ATR Smoothing Length + atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To + atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To + atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method + + // + // Presentation ... + showPV = true; // Show PV + showHK = true; // Show HK + showSAR = true; // Show Sar + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow + showMABand = true; // Show MA Band + showHKBand = true; // Show HK Band + showATRBand = true; // Show ATR Band + showZigZag = true; // Show ZigZag + 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; + showHK = false; + showSAR = false; + showMAFast = false; + showMASlow = false; + showMABand = false; + showHKBand = false; + showATRBand = false; + showZigZag = false; + showFiboZone = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // ATR ... + atrLength > 0 && + atrMultiplier >= 1 && + IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType) && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; + } +}; + +// +// Conditions ... +struct XFIMAConditions +{ + // + // 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 maBandUpperBuffer[]; + double maBandLowerBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboMiddleBuffer[]; + double fiboLowerBuffer[]; + double zigzagBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double highsBuffer[]; + double highsTimeBuffer[]; + double lowsBuffer[]; + double lowsTimeBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkLowBuffer[]; + double hkCloseBuffer[]; + double hkColorBuffer[]; + + // + // Conditions ... + + // + // Constructor ... + XFIMAConditions() + { + 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(maBandUpperBuffer); + SpecifiedClean(maBandLowerBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(sarColorBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(fiboUpperBuffer); + SpecifiedClean(fiboMiddleBuffer); + SpecifiedClean(fiboLowerBuffer); + SpecifiedClean(zigzagBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + SpecifiedClean(highsBuffer); + SpecifiedClean(highsTimeBuffer); + SpecifiedClean(lowsBuffer); + SpecifiedClean(lowsTimeBuffer); + SpecifiedClean(hkOpenBuffer); + SpecifiedClean(hkHighBuffer); + SpecifiedClean(hkLowBuffer); + SpecifiedClean(hkCloseBuffer); + SpecifiedClean(hkColorBuffer); + + // + // Conditions ... + + // + ArraySetAsSeries(bars, true); + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboMiddleBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(zigzagBuffer, false); // Fix this ... + 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(highsBuffer, true); + ArraySetAsSeries(highsTimeBuffer, true); + ArraySetAsSeries(lowsBuffer, true); + ArraySetAsSeries(lowsTimeBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(hkColorBuffer, 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 GetToken(this); + } +}; + +// +// Class ... +class XCXFIMAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + XCMarketPatternDetector *patternDetector; + + // + // Constructors ... + XCXFIMAHelper() + : XCBaseHelper(_Symbol, _Period) + { + patternDetector = new XCMarketPatternDetector(); + } + + // + // Deconstructor ... + ~XCXFIMAHelper() + { + // + delete patternDetector; + ZeroMemory(patternDetector); + } + + // + // Tools ... + + // + // Initialize Helper Cleass ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XFIMAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xfima", + "", // Calculation ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, + mInputs.fiboUpperZoneLevel, + mInputs.fiboMiddleZoneLevel, + mInputs.fiboLowerZoneLevel, + mInputs.sarStep, + mInputs.sarMax, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.maFastLength, + mInputs.maSlowLength, + mInputs.maBandLength, + mInputs.zigzagDepth, + mInputs.zigzagDeviation, + mInputs.zigzagBackStep, + mInputs.zigzagUppersMode, + mInputs.zigzagLowersMode, + mInputs.hkIgnoreShadows, + mInputs.hkSmoothingLength, + mInputs.hkSmoothingMode, + mInputs.atrLength, + mInputs.atrMultiplier, + mInputs.atrSmoothingLength, + mInputs.atrUpperPriceType, + mInputs.atrLowerPriceType, + mInputs.atrSmoothingMode, + "", // Presentation ... + mInputs.showPV, + mInputs.showHK, + mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, + mInputs.showMABand, + mInputs.showHKBand, + mInputs.showATRBand, + mInputs.showZigZag, + mInputs.showFiboZone, + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peakArrowCode, + mInputs.valeArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XFIMAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XFIMAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs // + ); + } + + // + // Tools ... + + // + bool GetConditions( + XFIMAConditions &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 // + ); + + // + CopyMABandUpper( + zIndex, + loopback, + conditions.maBandUpperBuffer // + ); + + // + CopyMABandLower( + zIndex, + loopback, + conditions.maBandLowerBuffer // + ); + + // + 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 // + ); + + // + CopyFiboMiddle( + zIndex, + loopback, + conditions.fiboMiddleBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + CopyZigZag( + zIndex, + loopback, + conditions.zigzagBuffer // + ); + + // + 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 // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyHKColor( + zIndex, + loopback, + conditions.hkColorBuffer // + ); + + // + // Conditions ... + + // + return result; + } + + // + // Pivot Actions ... + + /** + * Check Specified Bar has MA Cross or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * + * @return ( bool ) + */ + bool HasMACross( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + double validCrossDiffMultiplier = 1 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast[]; + int fastCount = CopyMAFast(barIndex, 2, fast); + + // + double slow[]; + int slowCount = CopyMASlow(barIndex, 2, slow); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(fastCount, slowCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(fast[0]) && + NotEmptyZero(fast[1]) && + NotEmptyZero(slow[0]) && + NotEmptyZero(slow[1]); + + // + isBullish = + notEmpty && + fast[0] > slow[0] && + fast[1] < slow[1]; + + // + isBearish = + notEmpty && + fast[0] < slow[0] && + fast[1] > slow[1]; + + // + result = + isBullish || + isBearish; + + // + // Validate Direction Change ... + if (result && + validCrossDiffMultiplier > 0) + { + // + double _points = GetPoints(GetSymbol()); + double diff = MathAbs(fast[0] - slow[0]); + + // + result = diff >= (validCrossDiffMultiplier * _points); + } + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + + // + return result; + } + + /** + * Check Specified Bar Price is In Boundary or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsInBoundary( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + // Read Boundary Values ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + result = value < max && + value > min; + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar Price is Over Boundary Min ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsOverBoundaryMin( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value > min; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar Price is Under Boundary Max ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsUnderBoundaryMax( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value < max; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Boundary Fake Breaked or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ + bool IsBoundaryFakeBreaked( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_CLOSE; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_CLOSE; + } + + // + // Initial Bars ... + XOHCL bar; + XOHCL pBar; + double min; + double max; + double pMin; + double pMax; + double boundaryValues[]; + result = + bar.Init( + mSymbol, + mPeriod, + barIndex // + ) && + bar.GetPreviousBar(pBar) && + GetBoundaryValues(min, max, barIndex) && + GetBoundaryValues(pMin, pMax, barIndex + 1) && + FillBoundaryValues(boundaryValues, barIndex) > 0; + + // + bool isBullish = + result && + pBar.IsBearish() && + bar.IsBullish() && + pBar.GetPrice(underMinPriceType) < pMin && + bar.GetPrice(underMinPriceType) > min && + (bar.GetPrice(underMinPriceType) > FindLesserThan(max, boundaryValues) || + bar.GetPrice(underMinPriceType) > FindBiggerThan(min + ((max - min) / 2), boundaryValues)); + + // + bool isBearish = + result && + pBar.IsBullish() && + bar.IsBearish() && + pBar.GetPrice(overMaxPriceType) > pMax && + bar.GetPrice(overMaxPriceType) < max && + (bar.GetPrice(overMaxPriceType) < FindBiggerThan(min, boundaryValues) || + bar.GetPrice(overMaxPriceType) < FindLesserThan(min + ((max - min) / 2), boundaryValues)); + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Cleanup ... + bar.Clean(); + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar's Price in Hot Place or Not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ + bool IsInHotPlace( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_LOW; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_HIGH; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Initialize Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double overMaxPrice = bar.GetPrice(overMaxPriceType); + double underMinPrice = bar.GetPrice(underMinPriceType); + + // + // Reading Boundary Value ... + double min; + double max; + result = GetBoundaryValues( + min, + max, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = underMinPrice < min; + bool isBearish = overMaxPrice > max; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar price Crossed in Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsCrossedInBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Check PrevBar Is in Hot Place ... + result = IsInHotPlace( + dir, + pBarIndex, + X_PRICE_LOW, + X_PRICE_HIGH // + ); + if (!result) + { + // + dir = X_DIRECTION_NONE; + + // + return result; + } + + // + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Current Bar must Into Boundary ... + result = IsInBoundary(priceType, barIndex); + if (!result) + { + dir = X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + + // + return result; + } + + /** + * Check Specified Bar price Crossed out Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsCrossedOutBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Prev Bar Must in Boundary ... + bool isBullish = IsInBoundary(X_PRICE_LOW, pBarIndex); + bool isBearish = IsInBoundary(X_PRICE_HIGH, pBarIndex); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Current Bar must Out of Boundary ... + + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + isBullish = + result && + isBullish && + bar.IsBullish() && + !IsInBoundary(priceType, barIndex); + + // + isBearish = + result && + isBearish && + bar.IsBearish() && + !IsInBoundary(priceType, barIndex); + + // + result = isBullish || + isBearish; + if (!result) + { + // + bar.Clean(); + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Boundary Trend or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasBoundaryTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower); + if (!result) + { + return result; + } + + // + bool isBullish = + fast > hkBandLower && + slow > hkBandLower && + maBandUpper > hkBandLower && + maBandLower > hkBandLower && + pbBandUpper > hkBandLower && + pbBandLower > hkBandLower; + bool isBearish = + fast < hkBandUpper && + slow < hkBandUpper && + maBandUpper < hkBandUpper && + maBandLower < hkBandUpper && + pbBandUpper < hkBandUpper && + pbBandLower < hkBandUpper; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specified Bar has Boundary Trend Switched or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasBoundarySwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = HasBoundaryTrend( + dir, + barIndex // + ); + if (!result) + { + return result; + } + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + result = HasBoundaryTrend( + dir, + barIndex + 1 // + ); + if (!result) + { + return result; + } + bool isPBullish = IsXBullish(dir); + bool isPBearish = IsXBearish(dir); + + // + bool isSwitchedToBullish = + isBullish && !isPBullish; + bool isSwitchedToBearish = + isBearish && !isPBearish; + result = isSwitchedToBullish || + isSwitchedToBearish; + if (result) + { + // + dir = isSwitchedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Fibo Section is Changed or not ... + * + * @param dir: reference to hold section change direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsFiboSectionChanged( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Reading Values ... + + // + double iFiboUpper = GetFiboUpper(barIndex); + double pFiboUpper = GetFiboUpper(barIndex + 1); + + // + double iFiboMiddle = GetFiboMiddle(barIndex); + double pFiboMiddle = GetFiboMiddle(barIndex + 1); + + // + double iFiboLower = GetFiboLower(barIndex); + double pFiboLower = GetFiboLower(barIndex + 1); + + // + isBullish = iFiboLower >= pFiboMiddle && + iFiboMiddle >= pFiboUpper; + isBearish = iFiboUpper <= pFiboMiddle && + iFiboMiddle <= pFiboLower; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Check for Fibo Push Exists or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold result ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ + bool HasFiboPush( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL iBar; + bool isBullish = false; + bool isBearish = false; + + // + double iFiboUpper = EMPTY_VALUE; + double pFiboUpper = EMPTY_VALUE; + + // + double iFiboMiddle = EMPTY_VALUE; + double pFiboMiddle = EMPTY_VALUE; + + // + double iFiboLower = EMPTY_VALUE; + double pFiboLower = EMPTY_VALUE; + + // + // Check Zone Validation ... + int start = barIndex; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Values ... + + // + iFiboUpper = GetFiboUpper(i); + pFiboUpper = GetFiboUpper(i + 1); + + // + iFiboMiddle = GetFiboMiddle(i); + pFiboMiddle = GetFiboMiddle(i + 1); + + // + iFiboLower = GetFiboLower(i); + pFiboLower = GetFiboLower(i + 1); + + // + result = iFiboUpper == pFiboUpper; + if (!result) + { + break; + } + } + + // + if (result) + { + // + result = iBar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + if (result) + { + // + iFiboUpper = GetFiboUpper(barIndex); + iFiboMiddle = GetFiboMiddle(barIndex); + iFiboLower = GetFiboLower(barIndex); + + // + isBullish = iBar.IsBullish() && + iBar.close > iFiboLower && + iBar.low < iFiboLower; + isBearish = iBar.IsBearish() && + iBar.close < iFiboUpper && + iBar.high > iFiboUpper; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Has Higher Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagHigherLow( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value > vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > vales[0].value && + bar.close > vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + /** + * Check Has Lower Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagLowerLow( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value < vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < vales[0].value && + bar.close < vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + /** + * Check Has Higher High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagHigherHigh( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value > peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > peaks[0].value && + bar.close > peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + /** + * Check Has Lower High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagLowerHigh( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value < peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < peaks[0].value && + bar.close < peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // SAR ... + + /** + * Check Specified Bar has SAR Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasSARSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double sars[]; + int count = CopySarState(barIndex, 2, sars); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + isBullish = + sars[0] >= 1 && + sars[1] <= -1; + + // + isBearish = + sars[0] <= -1 && + sars[1] >= 1; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(sars); + + // + return result; + } + + bool IsSarBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = GetSarState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsSarBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = GetSarState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsSarSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBullish = IsSarBullish(barIndex); + bool isPBullish = IsSarBullish(pBarIndex); + + // + result = isBullish && + !isPBullish; + + // + return result; + } + + bool IsSarSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBearish = IsSarBearish(barIndex); + bool isPBearish = IsSarBearish(pBarIndex); + + // + result = isBearish && + !isPBearish; + + // + return result; + } + + // + // PV ... + + bool IsPeakSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = GetPeak(barIndex); + double iP = GetPeak(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + bool IsValeSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = GetVale(barIndex); + double iP = GetVale(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + /** + * Check Peak Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = GetPeak(barIndex); + double pPeak = GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak > pPeak; + + // + return result; + } + + /** + * Check Vale Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = GetVale(barIndex); + double pVale = GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale > pVale; + + // + return result; + } + + /** + * Check Peak Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = GetPeak(barIndex); + double pPeak = GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak < pPeak; + + // + return result; + } + + /** + * Check Vale Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = GetVale(barIndex); + double pVale = GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale < pVale; + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Count Same Peaks ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSamePeaks( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double peak = GetPeak(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iPeak = GetPeak(idx); + has = peak == iPeak; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Same Vales ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSameVales( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iVale = EMPTY_VALUE; + double vale = GetVale(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iVale = GetVale(idx); + has = vale == iVale; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + bool HasPVConsolidationZone( + XBoxZone &zone, + int barIndex = 0, + bool forcePVBreak = false, + bool forceHasSarSwitch = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool isPeakSame = IsPeakSame(barIndex); + bool isValeSame = IsValeSame(barIndex); + result = !(isPeakSame && + isValeSame); + if (!result) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double iVale = EMPTY_VALUE; + + // + int idx = barIndex; + bool canLookup = true; + while (canLookup) + { + // + idx++; + isPeakSame = IsPeakSame(idx); + isValeSame = IsValeSame(idx); + result = isPeakSame && + isValeSame; + if (!result) + { + // + zone.from = GetBarTime(mSymbol, mPeriod, idx); + break; + } + + // + if (idx == barIndex + 1) + { + // + zone.to = GetBarTime( + mSymbol, + mPeriod, + idx // + ); + } + + // + zone.from = GetBarTime( + mSymbol, + mPeriod, + idx // + ); + + // + iPeak = GetPeak(idx); + iVale = GetVale(idx); + + // + zone.lower = + !NotEmptyZero(zone.lower) + ? iVale + : MathMin(zone.lower, iVale); + + // + zone.upper = + !NotEmptyZero(zone.upper) + ? iPeak + : MathMax(zone.upper, iPeak); + } + + // + // Validating Zone Params ... + result = + // + IsXValid(zone.to) && + IsXValid(zone.from) && + zone.from < zone.to && + // + NotEmptyZero(zone.lower) && + NotEmptyZero(zone.upper) && + zone.upper > zone.lower + // + ; + + // + // Prepare Zone ... + if (result) + { + // + iPeak = GetPeak(barIndex); + iVale = GetVale(barIndex); + bool isPeakOverLast = IsPeakOverLast(barIndex); + bool isValeUnderLast = IsValeUnderLast(barIndex); + bool isValeBreak = iVale < zone.lower; + bool isPeakBreak = iPeak > zone.upper; + bool isPVBreak = isPeakBreak || + isValeBreak; + + // + zone.at = GetBarTime(mSymbol, mPeriod, barIndex); + zone.symbol = mSymbol; + zone.period = mPeriod; + zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) + ? X_DIRECTION_BULLISH + : (isValeUnderLast && !isPeakOverLast && isPVBreak) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Refine Zone Upper and Lower ... + if (zone.IsValid()) + { + // + XOHCL iBar; + int zoneLoopback = zone.FromIndex() - zone.ToIndex(); + result = zone.ToBar(iBar) && + IsValidSize(zoneLoopback); + if (result) + { + // + double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); + double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); + result = NotEmptyZero(zoneLL) && + NotEmptyZero(zoneHH); + if (result) + { + // + zone.lower = zone.lower == zoneLL + ? zone.lower + : MathMax(zone.lower, zoneLL); + + // + zone.upper = zone.upper == zoneHH + ? zone.upper + : MathMin(zone.upper, zoneHH); + } + } + + // + iBar.Clean(); + } + + // + // Validate ... + result = zone.IsValid(); + } + + // + // Validate Zones From ... + if (result) + { + // + int idx = zone.FromIndex(); + + // + iPeak = GetPeak(idx); + iVale = GetVale(idx); + + // + bool isValeOverLast = IsValeOverLast(idx); + bool isPeakUnderLast = IsPeakUnderLast(idx); + + // + result = + result && + (zone.IsBullish() + ? !isPeakUnderLast + : zone.IsBearish() + ? !isValeOverLast + : false); + } + + // + // Apply Forces ... + + // + // PV Break ... + // Peak or Vale must Breaked at Bar ... + if (result && forcePVBreak) + { + // + bool isPVBreaked = + (zone.IsBullish() && IsPeakOverLast(barIndex)) || + (zone.IsBearish() && IsValeUnderLast(barIndex)); + + // + result = result && + isPVBreaked; + } + + // + // Other Loop based Forces ... + if (result && (forceHasSarSwitch)) + { + + // + bool hasSarSwitch = false; + + // + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + // Check Sar Switches ... + if (forceHasSarSwitch && !hasSarSwitch) + { + // + hasSarSwitch = + zone.IsBullish() + ? IsSarSwitchedToBullish(i) + : IsSarSwitchedToBearish(i); + } + } + + // + // Validate Forces ... + if (forceHasSarSwitch) + { + // + result = + result && + hasSarSwitch; + } + } + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + // + // HK ... + + /** + * Check Specified Bar has HK Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasHKSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + double open[]; + int openCount = CopyHKOpen(barIndex, 2, open); + + // + double close[]; + int closeCount = CopyHKClose(barIndex, 2, close); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(openCount, closeCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + + // + isBullish = + notEmpty && + open[0] < close[0] && + open[1] > close[1]; + + // + isBearish = + notEmpty && + open[0] > close[0] && + open[1] < close[1]; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + + // + return result; + } + + /** + * Check Specified Bar has HK Band Based Trend or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ + bool HasHKBasedTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Define Requirements ... + XOHCL iBar; + double hkUpper; + double hkLower; + bool has = false; + int bullishCount = 0; + int bearishCount = 0; + bool isBullish = false; + bool isBearish = false; + + // + // Count Bullish/Bearish Directions ... + int start = barIndex + 1; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Requirements ... + + // + // Read Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + mSymbol, + mPeriod, + i // + ); + if (!result) + { + break; + } + + // + // Reading Values ... + hkUpper = GetHKBandUpper(i); + hkLower = GetHKBandLower(i); + result = NotEmptyZero(hkUpper) && + NotEmptyZero(hkLower); + if (!result) + { + return result; + } + + // + // Check Trend ... + + // + // Bullish ... + isBullish = iBar.low > hkLower; + if (isBullish) + { + bullishCount++; + } + + // + // Bearish ... + isBearish = iBar.high < hkUpper; + if (isBearish) + { + bearishCount++; + } + + // + iBar.Clean(); + + // + } + + // + // Validate Results ... + isBullish = + bullishCount >= validationLength; + isBearish = + bearishCount >= validationLength; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + + // + // Setting Direction if Has Trend ... + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has HK Band Based Trend Switch or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ + bool IsHKBasedTrendSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool hasTrend = HasHKBasedTrend( + dir, + barIndex, + validationLength // + ); + bool isBullish = hasTrend && + IsXBullish(dir); + bool isBearish = hasTrend && + IsXBearish(dir); + + // + bool hasPTrend = HasHKBasedTrend( + dir, + barIndex + 1, + validationLength // + ); + bool isPBullish = hasPTrend && + IsXBullish(dir); + bool isPBearish = hasPTrend && + IsXBearish(dir); + + // + dir = X_DIRECTION_NONE; + + // + // Checking Result ... + isBullish = isBullish && !isPBullish; + isBearish = isBearish && !isPBearish; + + // + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + + // + return result; + } + + /** + * Check if Price Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check if Price Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check if Price Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check if Price Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price Switched Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Check Price Switched Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Check Price Switched Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Check Price Switched Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + // + // ZigZag Pivots With Liquidity ... + + /** + * Check ZigZag has Lower Low by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagLowerLowByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value < selected[1].value && + // + // Check Liquidity ... + selected[1].value > selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open > selected[0].value && + bar.close > selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + /** + * Check ZigZag has Higher High by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagHigherHighByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value > selected[1].value && + // + // Check Liquidity ... + selected[1].value < selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open < selected[0].value && + bar.close < selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Extractions ... + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( int ) + */ + int ExtractPVPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + bool lookupPeaks = true; + bool lookupVales = true; + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + int samePeaksCount = 0; + int sameValesCount = 0; + double tmpPeaksBuffer[]; + double tmpValesBuffer[]; + string symbol = GetSymbol(); + double iPValue = EMPTY_VALUE; + double iVValue = EMPTY_VALUE; + double pPValue = EMPTY_VALUE; + double pVValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Detecting ... + + // + // Peak ... + if (lookupPeaks) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_PEAK_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpPeaksBuffer // Buffer ... + ); + ArraySetAsSeries(tmpPeaksBuffer, true); + + // + // Reading Values ... + iPValue = tmpPeaksBuffer[0]; + pPValue = tmpPeaksBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iPValue)) + { + // + // Check New Peak ... + has = + !NotEmptyZero(pPValue) + ? true + : iPValue != pPValue; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + iPValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : samePeaksCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iPValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + samePeaksCount = 0; + } + else if (iPValue == pPValue) + { + samePeaksCount++; + } + } + } + + // + // Vale ... + if (lookupVales) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_VALE_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpValesBuffer // Buffer ... + ); + ArraySetAsSeries(tmpValesBuffer, true); + + // + // Reading Values ... + iVValue = tmpValesBuffer[0]; + pVValue = tmpValesBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iVValue)) + { + // + // Check New Vale ... + has = + !NotEmptyZero(pVValue) + ? true + : iVValue != pVValue; + if (has) + { + // + // Calculate and Validate Type ... + // Vales Only Valid when Confirmed by Bar Low ... + iType = + iVValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : sameValesCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iVValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + sameValesCount = 0; + } + else if (iVValue == pVValue) + { + sameValesCount++; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + double validCrossDiffMultiplier = 1, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double fast[]; + double slow[]; + XPivot iPivot; + int count = 0; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + double iFValue = EMPTY_VALUE; + double pFValue = EMPTY_VALUE; + double iSValue = EMPTY_VALUE; + double pSValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int fastCount = CopyMAFast(idx, 2, fast); + int slowCount = CopyMASlow(idx, 2, slow); + count = MathMin(fastCount, slowCount); + has = IsValidSize(count); + + // + // Reading Values ... + + // + iFValue = fast[0]; + pFValue = fast[1]; + + // + iSValue = slow[0]; + pSValue = slow[1]; + + // + // Validate Value ... + has = + HasMACross( + iDir, + idx, + validCrossDiffMultiplier // + ) && + NotEmptyZero(iFValue) && + NotEmptyZero(iSValue) && + NotEmptyZero(pFValue) && + NotEmptyZero(pSValue); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(iFValue, iSValue) + : MathMin(iFValue, iSValue); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_MA_CROSS); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractHKPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double open[]; + XPivot iPivot; + int count = 0; + double close[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int openCount = CopyHKOpen(idx, 2, open); + int closeCount = CopyHKClose(idx, 2, close); + count = MathMin(openCount, closeCount); + has = IsValidSize(count); + + // + // Validate Value ... + has = + HasHKSwitch( + iDir, + idx // + ) && + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_HK); + + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(open[0], close[0]) + : MathMin(open[0], close[0]); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractSARPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XOHCL pBar; + XPivot iPivot; + bool has = false; + double tmpSarBuffer[]; + int idx = barIndex - 1; + string symbol = GetSymbol(); + double iValue = EMPTY_VALUE; + double pValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + has = + has && + iBar.GetPreviousBar(pBar); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_SAR_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpSarBuffer // Buffer ... + ); + ArraySetAsSeries(tmpSarBuffer, true); + + // + // Reading Values ... + iValue = tmpSarBuffer[0]; + pValue = tmpSarBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iValue)) + { + // + // Check Sar Direction Changed ... + isSwitchedToBullish = iValue < iBar.low && + pValue > pBar.high; + isSwitchedToBearish = iValue > iBar.high && + pValue < pBar.low; + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_SAR_SWITCH); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractZigZagPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + double iValue = EMPTY_VALUE; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 1, // Number of Requirements ... + tmpZigZagBuffer // Buffer ... + ); + ArraySetAsSeries(tmpZigZagBuffer, true); + + // + // Read and Validate Value ... + iValue = tmpZigZagBuffer[0]; + has = NotEmptyZero(iValue); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Type ... + iType = + iValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : iValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Dir ... + iDir = + IsXVale(iType) + ? X_DIRECTION_BULLISH + : IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_ZIGZAG); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + return result; + } + + /** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ + int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + bool has = false; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double up = EMPTY_VALUE; + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double close = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + low = GetHKLow(i); + open = GetHKOpen(i); + high = GetHKHigh(i); + close = GetHKClose(i); + + // + // Initialized Start Bar ... + if (i == start) + { + // + startHKLow = low; + startHKOpen = open; + startHKHigh = high; + startHKClose = close; + } + + // + // Check Direction ... + isBullish = open < close; + isBearish = open > close; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Calculate Requirements for Processing ... + up = isBullish + ? close + : open; + down = isBullish + ? open + : close; + body = MathAbs(up - down); + range = high - low; + highShadow = high - up; + lowShadow = down - low; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? high + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? low + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = ToXString(XFIMA_PIVOT_HK) + "_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : ""); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + return result; + } + + // + // Values Retrievers ... + + /** + * Filling Specified Bar index Boundary Values ... + * + * @param dest: double, reference collection to hold boundary Values ... + * @param barIndex: int, Specified Bar's Index ... + * @param containsFastSlow: bool, Contains XMA Fast / Slow ... + * @param containsMABand: bool, Contains XMA Boundary Upper / Lower ... + * @param containsHKBound: bool, Contains XHK Boundary Upper / Lower ... + * @param containsPBBand: bool, Contains XPB Boundary Upper / Lower ... + * @param containsFiboLevels: nool, Contains XFIBO Levels ... + * + * @return ( int ) + */ + int FillBoundaryValues( + double &dest[], + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Read and Validate Values ... + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + has = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!has) + { + return result; + } + + // + // Fill Dest ... + + // + // XMA Fast / Slow ... + if (containsFastSlow) + { + // + Add(fast, dest); + Add(slow, dest); + } + + // + // XMA Bound ... + if (containsMABand) + { + // + Add(maBandUpper, dest); + Add(maBandLower, dest); + } + + // + // XHK Band ... + if (containsHKBound) + { + // + Add(hkBandUpper, dest); + Add(hkBandLower, dest); + } + + // + // XPB Band ... + if (containsPBBand) + { + // + Add(pbBandUpper, dest); + Add(pbBandLower, dest); + } + + // + // XFIBO Zones ... + if (containsFiboLevels) + { + // + Add(fiboLower, dest); + Add(fiboUpper, dest); + Add(fiboMiddle, dest); + } + + // + result = ArraySize(dest); + + // + return result; + } + + /** + * Retrieve Fast, Slow, MA Band Upper/Lower, HK Band Upper/Lower and PB Band Upper/Lower Min/Max ... + * + * @param min: double, minimum value ... + * @param max: double, maximum value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool GetBoundaryValues( + double &min, + double &max, + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // + ) + { + // + bool result = false; + + // + // Prepare ... + min = EMPTY_VALUE; + max = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!result) + { + return result; + } + + // + double values[]; + + // + if (containsFastSlow) + { + // + Add(fast, values); + Add(slow, values); + } + + // + if (containsMABand) + { + // + Add(maBandUpper, values); + Add(maBandLower, values); + } + + // + if (containsHKBound) + { + // + Add(hkBandUpper, values); + Add(hkBandLower, values); + } + + // + if (containsPBBand) + { + // + Add(pbBandUpper, values); + Add(pbBandLower, values); + } + + // + if (containsFiboLevels) + { + // + Add(fiboLower, values); + Add(fiboUpper, values); + Add(fiboMiddle, values); + } + + // + result = HasChild(values); + if (!result) + { + return result; + } + + // + min = GetMin(values); + max = GetMax(values); + + // + result = + NotEmptyZero(min) && + NotEmptyZero(max) && + min < max; + + // + return result; + } + + // + // Fast MA ... + + // + double GetMAFast( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_LINE, + barIndex // + ); + } + + // + int CopyMAFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_LINE, + start, + count, + asSeries // + ); + } + + // + // Fast MA State ... + + // + double GetMAFastState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_STATE_LINE, + barIndex // + ); + } + + // + int CopyMAFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA ... + + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_LINE, + barIndex // + ); + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA State ... + + // + double GetMASlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyMASlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper MA ... + + // + double GetMABandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyMABandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower MA ... + + // + double GetMABandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyMABandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XPB ... + + // + // Upper PB ... + + // + double GetPBBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyPBBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower PB ... + + // + double GetPBBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyPBBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper PB ... + + // + double GetPBRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyPBRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower PB ... + + // + double GetPBRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyPBRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XATR ... + + // + // Upper ATR ... + + // + double GetATRBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_LINE, + barIndex // + ); + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper ATR ... + + // + double GetATRRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_LINE, + barIndex // + ); + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_STATE_LINE, + barIndex // + ); + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PEAK_LINE, + barIndex // + ); + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PEAK_LINE, + start, + count, + asSeries // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_VALE_LINE, + barIndex // + ); + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_VALE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Zone ... + + // + // FIBO Upper ... + + // + double GetFiboUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_UPPER_LINE, + barIndex // + ); + } + + // + int CopyFiboUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Middle ... + + // + double GetFiboMiddle( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_MIDDLE_LINE, + barIndex // + ); + } + + // + int CopyFiboMiddle( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_MIDDLE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Lower ... + + // + double GetFiboLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_LOWER_LINE, + barIndex // + ); + } + + // + int CopyFiboLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ZigZag ... + + // + double GetZigZag( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ZIGZAG_LINE, + barIndex // + ); + } + + // + int CopyZigZag( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ZIGZAG_LINE, + start, + count, + asSeries // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_HH_LINE, + barIndex // + ); + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_LL_LINE, + barIndex // + ); + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_HH_LINE, + barIndex // + ); + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_LL_LINE, + barIndex // + ); + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_HH_LINE, + barIndex // + ); + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_LL_LINE, + barIndex // + ); + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_HH_LINE, + barIndex // + ); + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_LL_LINE, + barIndex // + ); + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK ... + + // + // XHK Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Color ... + + // + double GetHKColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_COLOR_LINE, + barIndex // + ); + } + + // + int CopyHKColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_COLOR_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw ... + + // + // XHK Raw Open ... + + // + double GetHKRawOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKRawOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw High ... + + // + double GetHKRawHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKRawHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw Low ... + + // + double GetHKRawLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKRawLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw Close ... + + // + double GetHKRawClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKRawClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Band ... + + // + // XHK Band Upper ... + + // + double GetHKBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyHKBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Band Lower ... + + // + double GetHKBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyHKBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XFIMAInputs mInputs; // Inputs ... + + // + // XHK Helper ... + + /** + * Validate HK Zone ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param validationLength: int, Validation Length of Zones ... + * @param breakValidLength: int, Break Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * + * @return ( bool ) + */ + bool ValidateHKZone( + XBoxZone &zone, + int validationLength = 1, + int breakValidLength = 3, + bool validateFakeBreakes = true // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + breakValidLength = NormalizeInt(breakValidLength, 2); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Requirements ... + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double close = EMPTY_VALUE; + + // + int count = 0; + int start = zone.FromIndex() + 1; + int end = start + validationLength; + + // + // Validate Before ... + for (int i = start; i < end; i++) + { + // + // Reading HK ... + low = GetHKLow(i); + high = GetHKHigh(i); + result = + NotEmptyZero(low) && + NotEmptyZero(high); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low > zone.lower + : high < zone.upper; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = start; i < end; i++) + { + // + // Read HK ... + low = GetHKLow(i); + high = GetHKHigh(i); + result = + NotEmptyZero(low) && + NotEmptyZero(high); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low > zone.lower + : high < zone.upper; + if (!result) + { + // + // Check For Fake Breake ... + if (validateFakeBreakes && breakValidLength > 0) + { + // + result = i - 1 >= 0; + if (result) + { + // + for (int j = i - 1; j >= zone.ToIndex(); j--) + { + // + // Reading HK ... + close = GetHKClose(j); + result = NotEmptyZero(close); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? close > zone.upper + : close < zone.lower; + if (result) + { + // + result = MathAbs(j - i) <= breakValidLength; + if (result) + { + break; + } + } + } + } + } + + // + if (!result) + { + break; + } + } + } + } + + // + // Cleanup Resource ... + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper copy.mq5 new file mode 100644 index 0000000..0045785 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper copy.mq5 @@ -0,0 +1,3820 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXFIMAHelper +// 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.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_XFIMA_BUFFERS +{ + XFIMA_MA_FAST_LINE = 0, + XFIMA_MA_FAST_COLOR_LINE = 1, + XFIMA_MA_FAST_STATE_LINE = 19, + XFIMA_MA_SLOW_LINE = 2, + XFIMA_MA_SLOW_COLOR_LINE = 3, + XFIMA_MA_SLOW_STATE_LINE = 20, + XFIMA_SAR_LINE = 4, + XFIMA_SAR_COLOR_LINE = 5, + XFIMA_SAR_STATE_LINE = 21, + XFIMA_PEAK_LINE = 6, + XFIMA_VALE_LINE = 7, + XFIMA_FIBO_UPPER_LINE = 8, + XFIMA_FIBO_MIDDLE_LINE = 9, + XFIMA_FIBO_LOWER_LINE = 10, + XFIMA_ZIGZAG_LINE = 11, + XFIMA_MA_BAND_UPPER_LINE = 12, + XFIMA_MA_BAND_LOWER_LINE = 13, + XFIMA_ZIGZAG_HIGHS_LINE = 30, + XFIMA_ZIGZAG_HIGHS_TIME_LINE = 31, + XFIMA_ZIGZAG_LOWS_LINE = 32, + XFIMA_ZIGZAG_LOWS_TIME_LINE = 33, + // + XFIMA_HK_OPEN_LINE = 14, + XFIMA_HK_HIGH_LINE = 15, + XFIMA_HK_LOW_LINE = 16, + XFIMA_HK_CLOSE_LINE = 17, + XFIMA_HK_COLOR_LINE = 18, + // 19 Ma Fast State + // 20 Ma Slow State + // 21 Sar State + XFIMA_SC_HH_LINE = 22, + XFIMA_SC_LL_LINE = 23, + XFIMA_MC_HH_LINE = 24, + XFIMA_MC_LL_LINE = 25, + XFIMA_LC_HH_LINE = 26, + XFIMA_LC_LL_LINE = 27, + XFIMA_HC_HH_LINE = 28, + XFIMA_HC_LL_LINE = 29, + // 30 ZigZag Highs + // 31 ZigZag Highs Time + // 32 ZigZag Lows + // 33 ZigZag Lows Time +}; + +// +// Input Models ... +struct XFIMAInputs +{ + // + // 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 fiboUpperZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboLowerZoneLevel; // 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 + int maBandLength; // MA Band Length + int zigzagDepth; // ZigZag Depth + int zigzagDeviation; // ZigZag Deviation + int zigzagBackStep; // ZigZag Back Step + ENUM_X_PRICE zigzagUppersMode; // ZigZag High Detect Mode + ENUM_X_PRICE zigzagLowersMode; // ZigZag Low Detect Mode + + // + // Presentation ... + bool showPV; // Show PV + bool showHK; // Show HK + bool showSAR; // Show Sar + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow + bool showMABand; // Show MA Band + bool showZigZag; // Show ZigZag + 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) ... + XFIMAInputs() + { + 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 + fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level + fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level + fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 + maBandLength = 7; // MA Band Length + zigzagDepth = 12; // ZigZag Depth + zigzagDeviation = 5; // ZigZag Deviation + zigzagBackStep = 3; // ZigZag Back Step + zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode + zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + + // + // Presentation ... + showPV = true; // Show PV + showHK = true; // Show HK + showSAR = true; // Show Sar + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow + showMABand = true; // Show MA Band + showZigZag = true; // Show ZigZag + 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; + showHK = false; + showSAR = false; + showMAFast = false; + showMASlow = false; + showMABand = false; + showZigZag = false; + showFiboZone = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; + } +}; + +// +// Conditions ... +struct XFIMAConditions +{ + // + // 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 maBandUpperBuffer[]; + double maBandLowerBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboMiddleBuffer[]; + double fiboLowerBuffer[]; + double zigzagBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double highsBuffer[]; + double highsTimeBuffer[]; + double lowsBuffer[]; + double lowsTimeBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkLowBuffer[]; + double hkCloseBuffer[]; + double hkColorBuffer[]; + + // + // Conditions ... + + // + // Constructor ... + XFIMAConditions() + { + 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(maBandUpperBuffer); + SpecifiedClean(maBandLowerBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(sarColorBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(fiboUpperBuffer); + SpecifiedClean(fiboMiddleBuffer); + SpecifiedClean(fiboLowerBuffer); + SpecifiedClean(zigzagBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + SpecifiedClean(highsBuffer); + SpecifiedClean(highsTimeBuffer); + SpecifiedClean(lowsBuffer); + SpecifiedClean(lowsTimeBuffer); + SpecifiedClean(hkOpenBuffer); + SpecifiedClean(hkHighBuffer); + SpecifiedClean(hkLowBuffer); + SpecifiedClean(hkCloseBuffer); + SpecifiedClean(hkColorBuffer); + + // + // Conditions ... + + // + ArraySetAsSeries(bars, true); + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboMiddleBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(zigzagBuffer, false); // Fix this ... + 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(highsBuffer, true); + ArraySetAsSeries(highsTimeBuffer, true); + ArraySetAsSeries(lowsBuffer, true); + ArraySetAsSeries(lowsTimeBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(hkColorBuffer, 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 GetToken(this); + } +}; + +// +// Class ... +class XCXFIMAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCXFIMAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXFIMAHelper() + { + } + + // + // Tools ... + + // + // Initialize Helper Cleass ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XFIMAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xfima", + "", // Calculation ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, + mInputs.fiboUpperZoneLevel, + mInputs.fiboMiddleZoneLevel, + mInputs.fiboLowerZoneLevel, + mInputs.sarStep, + mInputs.sarMax, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.maFastLength, + mInputs.maSlowLength, + mInputs.maBandLength, + mInputs.zigzagDepth, + mInputs.zigzagDeviation, + mInputs.zigzagBackStep, + mInputs.zigzagUppersMode, + mInputs.zigzagLowersMode, + "", // Presentation ... + mInputs.showPV, + mInputs.showHK, + mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, + mInputs.showMABand, + mInputs.showZigZag, + mInputs.showFiboZone, + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peakArrowCode, + mInputs.valeArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XFIMAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XFIMAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs // + ); + } + + // + // Tools ... + + // + bool GetConditions( + XFIMAConditions &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 // + ); + + // + CopyMABandUpper( + zIndex, + loopback, + conditions.maBandUpperBuffer // + ); + + // + CopyMABandLower( + zIndex, + loopback, + conditions.maBandLowerBuffer // + ); + + // + 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 // + ); + + // + CopyFiboMiddle( + zIndex, + loopback, + conditions.fiboMiddleBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + CopyZigZag( + zIndex, + loopback, + conditions.zigzagBuffer // + ); + + // + 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 // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyHKColor( + zIndex, + loopback, + conditions.hkColorBuffer // + ); + + // + // Conditions ... + + // + return result; + } + + // + // Pivot Actions ... + + /** + * Check Specified Bar has MA Cross or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * + * @return ( bool ) + */ + bool HasMACross( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + double validCrossDiffMultiplier = 1 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + double fast[]; + double slow[]; + double upper[]; + double lower[]; + int count = ReadMAValues( + fast, + slow, + upper, + lower, + barIndex, + 2 // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(fast[0]) && + NotEmptyZero(fast[1]) && + NotEmptyZero(slow[0]) && + NotEmptyZero(slow[1]); + + // + isBullish = + notEmpty && + fast[0] > slow[0] && + fast[1] < slow[1]; + + // + isBearish = + notEmpty && + fast[0] < slow[0] && + fast[1] > slow[1]; + + // + result = + isBullish || + isBearish; + + // + // Validate Direction Change ... + if (result && + validCrossDiffMultiplier > 0) + { + // + double _points = GetPoints(GetSymbol()); + double diff = MathAbs(fast[0] - slow[0]); + + // + result = diff >= (validCrossDiffMultiplier * _points); + } + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + XClean(upper); + XClean(lower); + + // + return result; + } + + /** + * Check Specified Bar has HK Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasHKSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + double low[]; + double open[]; + double high[]; + double close[]; + int count = ReadHKBars( + open, + high, + low, + close, + barIndex, + 2 // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + + // + isBullish = + notEmpty && + open[0] < close[0] && + open[1] > close[1]; + + // + isBearish = + notEmpty && + open[0] > close[0] && + open[1] < close[1]; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(low); + XClean(open); + XClean(high); + XClean(close); + + // + return result; + } + + /** + * Check Specified Bar has SAR Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasSARSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + double sars[]; + int count = CopyBuffer( + mHandler, + XFIMA_SAR_STATE_LINE, + barIndex, + 2, + sars // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + isBullish = + sars[0] >= 1 && + sars[1] <= -1; + + // + isBearish = + sars[0] <= -1 && + sars[1] >= 1; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(sars); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( int ) + */ + int ExtractPVPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + bool lookupPeaks = true; + bool lookupVales = true; + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + int samePeaksCount = 0; + int sameValesCount = 0; + double tmpPeaksBuffer[]; + double tmpValesBuffer[]; + string symbol = GetSymbol(); + double iPValue = EMPTY_VALUE; + double iVValue = EMPTY_VALUE; + double pPValue = EMPTY_VALUE; + double pVValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Detecting ... + + // + // Peak ... + if (lookupPeaks) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_PEAK_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpPeaksBuffer // Buffer ... + ); + ArraySetAsSeries(tmpPeaksBuffer, true); + + // + // Reading Values ... + iPValue = tmpPeaksBuffer[0]; + pPValue = tmpPeaksBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iPValue)) + { + // + // Check New Peak ... + has = + !NotEmptyZero(pPValue) + ? true + : iPValue != pPValue; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + iPValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : samePeaksCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iPValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + samePeaksCount = 0; + } + else if (iPValue == pPValue) + { + samePeaksCount++; + } + } + } + + // + // Vale ... + if (lookupVales) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_VALE_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpValesBuffer // Buffer ... + ); + ArraySetAsSeries(tmpValesBuffer, true); + + // + // Reading Values ... + iVValue = tmpValesBuffer[0]; + pVValue = tmpValesBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iVValue)) + { + // + // Check New Vale ... + has = + !NotEmptyZero(pVValue) + ? true + : iVValue != pVValue; + if (has) + { + // + // Calculate and Validate Type ... + // Vales Only Valid when Confirmed by Bar Low ... + iType = + iVValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : sameValesCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iVValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + sameValesCount = 0; + } + else if (iVValue == pVValue) + { + sameValesCount++; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + double validCrossDiffMultiplier = 1, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double fast[]; + double slow[]; + XPivot iPivot; + int count = 0; + double upper[]; + double lower[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + double iFValue = EMPTY_VALUE; + double pFValue = EMPTY_VALUE; + double iSValue = EMPTY_VALUE; + double pSValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iPivot.Clean(); + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + count = ReadMAValues( + fast, + slow, + upper, + lower, + idx, + 2 // + ); + has = IsValidSize(count); + + // + // Reading Values ... + + // + iFValue = fast[0]; + pFValue = fast[1]; + + // + iSValue = slow[0]; + pSValue = slow[1]; + + // + // Validate Value ... + has = + HasMACross( + iDir, + idx, + validCrossDiffMultiplier // + ) && + NotEmptyZero(iFValue) && + NotEmptyZero(iSValue) && + NotEmptyZero(pFValue) && + NotEmptyZero(pSValue); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(iFValue, iSValue) + : MathMin(iFValue, iSValue); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractHKPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double low[]; + double open[]; + XPivot iPivot; + int count = 0; + double high[]; + double close[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iPivot.Clean(); + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + count = ReadHKBars( + open, + high, + low, + close, + idx, + 2 // + ); + has = IsValidSize(count); + + // + // Validate Value ... + has = + HasHKSwitch( + iDir, + idx // + ) && + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(open[0], close[0]) + : MathMin(open[0], close[0]); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractSARPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XOHCL pBar; + XPivot iPivot; + bool has = false; + double tmpSarBuffer[]; + int idx = barIndex - 1; + string symbol = GetSymbol(); + double iValue = EMPTY_VALUE; + double pValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + has = + has && + iBar.GetPreviousBar(pBar); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_SAR_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpSarBuffer // Buffer ... + ); + ArraySetAsSeries(tmpSarBuffer, true); + + // + // Reading Values ... + iValue = tmpSarBuffer[0]; + pValue = tmpSarBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iValue)) + { + // + // Check Sar Direction Changed ... + isSwitchedToBullish = iValue < iBar.low && + pValue > pBar.high; + isSwitchedToBearish = iValue > iBar.high && + pValue < pBar.low; + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // TODO: we can also Add other Validations Here ... + + // + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractZigZagPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + double iValue = EMPTY_VALUE; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 1, // Number of Requirements ... + tmpZigZagBuffer // Buffer ... + ); + ArraySetAsSeries(tmpZigZagBuffer, true); + + // + // Read and Validate Value ... + iValue = tmpZigZagBuffer[0]; + has = NotEmptyZero(iValue); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Type ... + iType = + iValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : iValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Dir ... + iDir = + IsXVale(iType) + ? X_DIRECTION_BULLISH + : IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + return result; + } + + /** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ + int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + double hkLows[]; + bool has = false; + double hkOpens[]; + double hkHighs[]; + double hkCloses[]; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double up = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + count = ReadHKBars( + hkOpens, + hkHighs, + hkLows, + hkCloses, + i, + 1 // + ); + has = IsValidSize(count); + if (!has) + { + continue; + } + + // + // Initialized Start Bar ... + if (i == start) + { + // + startHKLow = hkLows[0]; + startHKOpen = hkOpens[0]; + startHKHigh = hkHighs[0]; + startHKClose = hkCloses[0]; + } + + // + // Check Direction ... + isBullish = hkOpens[0] < hkCloses[0]; + isBearish = hkOpens[0] > hkCloses[0]; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Calculate Requirements for Processing ... + up = isBullish + ? hkCloses[0] + : hkOpens[0]; + down = isBullish + ? hkOpens[0] + : hkCloses[0]; + body = MathAbs(up - down); + range = hkHighs[0] - hkLows[0]; + highShadow = hkHighs[0] - up; + lowShadow = down - hkLows[0]; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? hkHighs[0] + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? hkLows[0] + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = "XHK_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : "") + + "_" + ToXString(TimeToSeconds(zone.from)); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + SpecifiedClean(hkLows); + SpecifiedClean(hkOpens); + SpecifiedClean(hkHighs); + SpecifiedClean(hkCloses); + + // + return result; + } + + // + // Values Retrievers ... + + // + // Fast MA ... + + // + double GetMAFast( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_LINE, + barIndex // + ); + } + + // + int CopyMAFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_LINE, + start, + count, + asSeries // + ); + } + + // + // Fast MA State ... + + // + double GetMAFastState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_STATE_LINE, + barIndex // + ); + } + + // + int CopyMAFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA ... + + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_LINE, + barIndex // + ); + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA State ... + + // + double GetMASlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyMASlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper MA ... + + // + double GetMABandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyMABandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower MA ... + + // + double GetMABandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyMABandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_LINE, + barIndex // + ); + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_STATE_LINE, + barIndex // + ); + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PEAK_LINE, + barIndex // + ); + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PEAK_LINE, + start, + count, + asSeries // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_VALE_LINE, + barIndex // + ); + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_VALE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Zone ... + + // + // FIBO Upper ... + + // + double GetFiboUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_UPPER_LINE, + barIndex // + ); + } + + // + int CopyFiboUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Middle ... + + // + double GetFiboMiddle( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_MIDDLE_LINE, + barIndex // + ); + } + + // + int CopyFiboMiddle( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_MIDDLE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Lower ... + + // + double GetFiboLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_LOWER_LINE, + barIndex // + ); + } + + // + int CopyFiboLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ZigZag ... + + // + double GetZigZag( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ZIGZAG_LINE, + barIndex // + ); + } + + // + int CopyZigZag( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ZIGZAG_LINE, + start, + count, + asSeries // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_HH_LINE, + barIndex // + ); + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_LL_LINE, + barIndex // + ); + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_HH_LINE, + barIndex // + ); + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_LL_LINE, + barIndex // + ); + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_HH_LINE, + barIndex // + ); + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_LL_LINE, + barIndex // + ); + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_HH_LINE, + barIndex // + ); + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_LL_LINE, + barIndex // + ); + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK ... + + // + // XHK Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Color ... + + // + double GetHKColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_COLOR_LINE, + barIndex // + ); + } + + // + int CopyHKColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_COLOR_LINE, + start, + count, + asSeries // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XFIMAInputs mInputs; // Inputs ... + + // + // XHK Helper ... + + // + int ReadHKBars( + double &open[], + double &high[], + double &low[], + double &close[], + int barIndex = 0, + int count = 1 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + // Normalize ... + count = NormalizeInt(count, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + // Open ... + CopyBuffer( + mHandler, + XFIMA_HK_OPEN_LINE, + barIndex, + count, + open // + ); + + // + // High ... + CopyBuffer( + mHandler, + XFIMA_HK_HIGH_LINE, + barIndex, + count, + high // + ); + + // + // Low ... + CopyBuffer( + mHandler, + XFIMA_HK_LOW_LINE, + barIndex, + count, + low // + ); + + // + // Close ... + CopyBuffer( + mHandler, + XFIMA_HK_CLOSE_LINE, + barIndex, + count, + close // + ); + + // + ArraySetAsSeries(low, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(close, true); + + // + // Min Number of Array Sizes ... + result = MathMin(ArraySize(open), ArraySize(high)); + result = MathMin(result, ArraySize(close)); + result = MathMin(result, ArraySize(low)); + + // + return result; + } + + /** + * Validate HK Zone ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param validationLength: int, Validation Length of Zones ... + * @param breakValidLength: int, Break Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * + * @return ( bool ) + */ + bool ValidateHKZone( + XBoxZone &zone, + int validationLength = 1, + int breakValidLength = 3, + bool validateFakeBreakes = true // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + breakValidLength = NormalizeInt(breakValidLength, 2); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Requirements ... + double low[]; + double open[]; + double high[]; + int count = 0; + double close[]; + + // + int start = zone.FromIndex() + 1; + int end = start + validationLength; + + // + // Validate Before ... + for (int i = start; i < end; i++) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + i, + 1 // + ); + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low[0] > zone.lower + : high[0] < zone.upper; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = start; i < end; i++) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + i, + 1 // + ); + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low[0] > zone.lower + : high[0] < zone.upper; + if (!result) + { + // + // Check For Fake Breake ... + if (validateFakeBreakes && breakValidLength > 0) + { + // + result = i - 1 >= 0; + if (result) + { + // + for (int j = i - 1; j >= zone.ToIndex(); j--) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + j, + 1 // + ); + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? close[0] > zone.upper + : close[0] < zone.lower; + if (result) + { + // + result = MathAbs(j - i) <= breakValidLength; + if (result) + { + break; + } + } + } + } + } + + // + if (!result) + { + break; + } + } + } + } + + // + // Cleanup Resource ... + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + return result; + } + + // + int ReadMAValues( + double &fast[], + double &slow[], + double &upper[], + double &lower[], + int barIndex = 0, + int count = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + // Normalize ... + count = NormalizeInt(count, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + CopyBuffer( + mHandler, + XFIMA_MA_FAST_LINE, + barIndex, + count, + fast // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_SLOW_LINE, + barIndex, + count, + slow // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_BAND_UPPER_LINE, + barIndex, + count, + upper // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_BAND_LOWER_LINE, + barIndex, + count, + lower // + ); + + // + ArraySetAsSeries(fast, true); + ArraySetAsSeries(slow, true); + ArraySetAsSeries(upper, true); + ArraySetAsSeries(lower, true); + + // + result = MathMin(ArraySize(fast), ArraySize(slow)); + result = MathMin(result, ArraySize(upper)); + result = MathMin(result, ArraySize(lower)); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper.mq5 new file mode 100644 index 0000000..f9033b9 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.helper.mq5 @@ -0,0 +1,4974 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXFIMAHelper +// 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.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_XFIMA_BUFFERS +{ + XFIMA_MA_FAST_LINE = 0, + XFIMA_MA_FAST_COLOR_LINE = 1, + XFIMA_MA_FAST_STATE_LINE = 19, + XFIMA_MA_SLOW_LINE = 2, + XFIMA_MA_SLOW_COLOR_LINE = 3, + XFIMA_MA_SLOW_STATE_LINE = 20, + XFIMA_SAR_LINE = 4, + XFIMA_SAR_COLOR_LINE = 5, + XFIMA_SAR_STATE_LINE = 21, + XFIMA_PEAK_LINE = 6, + XFIMA_VALE_LINE = 7, + XFIMA_FIBO_UPPER_LINE = 8, + XFIMA_FIBO_MIDDLE_LINE = 9, + XFIMA_FIBO_LOWER_LINE = 10, + XFIMA_ZIGZAG_LINE = 11, + XFIMA_MA_BAND_UPPER_LINE = 12, + XFIMA_MA_BAND_LOWER_LINE = 13, + XFIMA_ZIGZAG_HIGHS_LINE = 30, + XFIMA_ZIGZAG_HIGHS_TIME_LINE = 31, + XFIMA_ZIGZAG_LOWS_LINE = 32, + XFIMA_ZIGZAG_LOWS_TIME_LINE = 33, + // + XFIMA_HK_OPEN_LINE = 14, + XFIMA_HK_HIGH_LINE = 15, + XFIMA_HK_LOW_LINE = 16, + XFIMA_HK_CLOSE_LINE = 17, + XFIMA_HK_COLOR_LINE = 18, + // 19 Ma Fast State + // 20 Ma Slow State + // 21 Sar State + XFIMA_SC_HH_LINE = 22, + XFIMA_SC_LL_LINE = 23, + XFIMA_MC_HH_LINE = 24, + XFIMA_MC_LL_LINE = 25, + XFIMA_LC_HH_LINE = 26, + XFIMA_LC_LL_LINE = 27, + XFIMA_HC_HH_LINE = 28, + XFIMA_HC_LL_LINE = 29, + // 30 ZigZag Highs + // 31 ZigZag Highs Time + // 32 ZigZag Lows + // 33 ZigZag Lows Time +}; + +// +// Input Models ... +struct XFIMAInputs +{ + // + // 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 fiboUpperZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboLowerZoneLevel; // 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 + int maBandLength; // MA Band Length + int zigzagDepth; // ZigZag Depth + int zigzagDeviation; // ZigZag Deviation + int zigzagBackStep; // ZigZag Back Step + ENUM_X_PRICE zigzagUppersMode; // ZigZag High Detect Mode + ENUM_X_PRICE zigzagLowersMode; // ZigZag Low Detect Mode + + // + // Presentation ... + bool showPV; // Show PV + bool showHK; // Show HK + bool showSAR; // Show Sar + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow + bool showMABand; // Show MA Band + bool showZigZag; // Show ZigZag + 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) ... + XFIMAInputs() + { + 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 + fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level + fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level + fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 + maBandLength = 7; // MA Band Length + zigzagDepth = 12; // ZigZag Depth + zigzagDeviation = 5; // ZigZag Deviation + zigzagBackStep = 3; // ZigZag Back Step + zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode + zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + + // + // Presentation ... + showPV = true; // Show PV + showHK = true; // Show HK + showSAR = true; // Show Sar + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow + showMABand = true; // Show MA Band + showZigZag = true; // Show ZigZag + 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; + showHK = false; + showSAR = false; + showMAFast = false; + showMASlow = false; + showMABand = false; + showZigZag = false; + showFiboZone = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; + } +}; + +// +// Conditions ... +struct XFIMAConditions +{ + // + // 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 maBandUpperBuffer[]; + double maBandLowerBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboMiddleBuffer[]; + double fiboLowerBuffer[]; + double zigzagBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double highsBuffer[]; + double highsTimeBuffer[]; + double lowsBuffer[]; + double lowsTimeBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkLowBuffer[]; + double hkCloseBuffer[]; + double hkColorBuffer[]; + + // + // Conditions ... + + // + // Constructor ... + XFIMAConditions() + { + 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(maBandUpperBuffer); + SpecifiedClean(maBandLowerBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(sarColorBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(fiboUpperBuffer); + SpecifiedClean(fiboMiddleBuffer); + SpecifiedClean(fiboLowerBuffer); + SpecifiedClean(zigzagBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + SpecifiedClean(highsBuffer); + SpecifiedClean(highsTimeBuffer); + SpecifiedClean(lowsBuffer); + SpecifiedClean(lowsTimeBuffer); + SpecifiedClean(hkOpenBuffer); + SpecifiedClean(hkHighBuffer); + SpecifiedClean(hkLowBuffer); + SpecifiedClean(hkCloseBuffer); + SpecifiedClean(hkColorBuffer); + + // + // Conditions ... + + // + ArraySetAsSeries(bars, true); + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboMiddleBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(zigzagBuffer, false); // Fix this ... + 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(highsBuffer, true); + ArraySetAsSeries(highsTimeBuffer, true); + ArraySetAsSeries(lowsBuffer, true); + ArraySetAsSeries(lowsTimeBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(hkColorBuffer, 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 GetToken(this); + } +}; + +// +// Class ... +class XCXFIMAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Buffers ... + double maFastBuffer[]; + double maFastColorBuffer[]; + double maFastStateBuffer[]; + double maSlowBuffer[]; + double maSlowColorBuffer[]; + double maSlowStateBuffer[]; + double maBandUpperBuffer[]; + double maBandLowerBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboMiddleBuffer[]; + double fiboLowerBuffer[]; + double zigzagBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double highsBuffer[]; + double highsTimeBuffer[]; + double lowsBuffer[]; + double lowsTimeBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkLowBuffer[]; + double hkCloseBuffer[]; + double hkColorBuffer[]; + + // + // Constructors ... + XCXFIMAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXFIMAHelper() + { + } + + // + // Tools ... + + // + // Initialize Helper Cleass ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XFIMAInputs &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(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboMiddleBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(zigzagBuffer, false); // TODO: FIX This ... + 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(highsBuffer, true); + ArraySetAsSeries(highsTimeBuffer, true); + ArraySetAsSeries(lowsBuffer, true); + ArraySetAsSeries(lowsTimeBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(hkColorBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xfima", + "", // Calculation ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, + mInputs.fiboUpperZoneLevel, + mInputs.fiboMiddleZoneLevel, + mInputs.fiboLowerZoneLevel, + mInputs.sarStep, + mInputs.sarMax, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.maFastLength, + mInputs.maSlowLength, + mInputs.maBandLength, + mInputs.zigzagDepth, + mInputs.zigzagDeviation, + mInputs.zigzagBackStep, + mInputs.zigzagUppersMode, + mInputs.zigzagLowersMode, + "", // Presentation ... + mInputs.showPV, + mInputs.showHK, + mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, + mInputs.showMABand, + mInputs.showZigZag, + mInputs.showFiboZone, + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peakArrowCode, + mInputs.valeArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XFIMAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XFIMAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs // + ); + } + + // + // Tools ... + + // + void Update( + int barIndex // Bar Index + ) + { + Calculate(barIndex); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + XFIMAConditions &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 // + ); + + // + CopyMABandUpper( + zIndex, + loopback, + conditions.maBandUpperBuffer // + ); + + // + CopyMABandLower( + zIndex, + loopback, + conditions.maBandLowerBuffer // + ); + + // + 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 // + ); + + // + CopyFiboMiddle( + zIndex, + loopback, + conditions.fiboMiddleBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + CopyZigZag( + zIndex, + loopback, + conditions.zigzagBuffer // + ); + + // + 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 // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyHKColor( + zIndex, + loopback, + conditions.hkColorBuffer // + ); + + // + // Conditions ... + + // + return result; + } + + // + // Pivot Actions ... + + /** + * Check Specified Bar has MA Cross or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * + * @return ( bool ) + */ + bool HasMACross( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + double validCrossDiffMultiplier = 1 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + double fast[]; + double slow[]; + double upper[]; + double lower[]; + int count = ReadMAValues( + fast, + slow, + upper, + lower, + barIndex, + 2 // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(fast[0]) && + NotEmptyZero(fast[1]) && + NotEmptyZero(slow[0]) && + NotEmptyZero(slow[1]); + + // + isBullish = + notEmpty && + fast[0] > slow[0] && + fast[1] < slow[1]; + + // + isBearish = + notEmpty && + fast[0] < slow[0] && + fast[1] > slow[1]; + + // + result = + isBullish || + isBearish; + + // + // Validate Direction Change ... + if (result && + validCrossDiffMultiplier > 0) + { + // + double _points = GetPoints(GetSymbol()); + double diff = MathAbs(fast[0] - slow[0]); + + // + result = diff >= (validCrossDiffMultiplier * _points); + } + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + XClean(upper); + XClean(lower); + + // + return result; + } + + /** + * Check Specified Bar has HK Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasHKSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + double low[]; + double open[]; + double high[]; + double close[]; + int count = ReadHKBars( + open, + high, + low, + close, + barIndex, + 2 // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + + // + isBullish = + notEmpty && + open[0] < close[0] && + open[1] > close[1]; + + // + isBearish = + notEmpty && + open[0] > close[0] && + open[1] < close[1]; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(low); + XClean(open); + XClean(high); + XClean(close); + + // + return result; + } + + /** + * Check Specified Bar has SAR Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasSARSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + double sars[]; + int count = CopyBuffer( + mHandler, + XFIMA_SAR_STATE_LINE, + barIndex, + 2, + sars // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + isBullish = + sars[0] >= 1 && + sars[1] <= -1; + + // + isBearish = + sars[0] <= -1 && + sars[1] >= 1; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(sars); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( int ) + */ + int ExtractPVPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + bool lookupPeaks = true; + bool lookupVales = true; + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + int samePeaksCount = 0; + int sameValesCount = 0; + double tmpPeaksBuffer[]; + double tmpValesBuffer[]; + string symbol = GetSymbol(); + double iPValue = EMPTY_VALUE; + double iVValue = EMPTY_VALUE; + double pPValue = EMPTY_VALUE; + double pVValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Detecting ... + + // + // Peak ... + if (lookupPeaks) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_PEAK_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpPeaksBuffer // Buffer ... + ); + ArraySetAsSeries(tmpPeaksBuffer, true); + + // + // Reading Values ... + iPValue = tmpPeaksBuffer[0]; + pPValue = tmpPeaksBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iPValue)) + { + // + // Check New Peak ... + has = + !NotEmptyZero(pPValue) + ? true + : iPValue != pPValue; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + iPValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : samePeaksCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iPValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + samePeaksCount = 0; + } + else if (iPValue == pPValue) + { + samePeaksCount++; + } + } + } + + // + // Vale ... + if (lookupVales) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_VALE_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpValesBuffer // Buffer ... + ); + ArraySetAsSeries(tmpValesBuffer, true); + + // + // Reading Values ... + iVValue = tmpValesBuffer[0]; + pVValue = tmpValesBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iVValue)) + { + // + // Check New Vale ... + has = + !NotEmptyZero(pVValue) + ? true + : iVValue != pVValue; + if (has) + { + // + // Calculate and Validate Type ... + // Vales Only Valid when Confirmed by Bar Low ... + iType = + iVValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : sameValesCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iVValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + sameValesCount = 0; + } + else if (iVValue == pVValue) + { + sameValesCount++; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + double validCrossDiffMultiplier = 1, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double fast[]; + double slow[]; + XPivot iPivot; + int count = 0; + double upper[]; + double lower[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + double iFValue = EMPTY_VALUE; + double pFValue = EMPTY_VALUE; + double iSValue = EMPTY_VALUE; + double pSValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iPivot.Clean(); + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + count = ReadMAValues( + fast, + slow, + upper, + lower, + idx, + 2 // + ); + has = IsValidSize(count); + + // + // Reading Values ... + + // + iFValue = fast[0]; + pFValue = fast[1]; + + // + iSValue = slow[0]; + pSValue = slow[1]; + + // + // Validate Value ... + has = + HasMACross( + iDir, + idx, + validCrossDiffMultiplier // + ) && + NotEmptyZero(iFValue) && + NotEmptyZero(iSValue) && + NotEmptyZero(pFValue) && + NotEmptyZero(pSValue); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(iFValue, iSValue) + : MathMin(iFValue, iSValue); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractHKPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double low[]; + double open[]; + XPivot iPivot; + int count = 0; + double high[]; + double close[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iPivot.Clean(); + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + count = ReadHKBars( + open, + high, + low, + close, + idx, + 2 // + ); + has = IsValidSize(count); + + // + // Validate Value ... + has = + HasHKSwitch( + iDir, + idx // + ) && + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(open[0], close[0]) + : MathMin(open[0], close[0]); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iPivot.Clean(); + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractSARPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XOHCL pBar; + XPivot iPivot; + bool has = false; + double tmpSarBuffer[]; + int idx = barIndex - 1; + string symbol = GetSymbol(); + double iValue = EMPTY_VALUE; + double pValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + has = + has && + iBar.GetPreviousBar(pBar); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_SAR_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpSarBuffer // Buffer ... + ); + ArraySetAsSeries(tmpSarBuffer, true); + + // + // Reading Values ... + iValue = tmpSarBuffer[0]; + pValue = tmpSarBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iValue)) + { + // + // Check Sar Direction Changed ... + isSwitchedToBullish = iValue < iBar.low && + pValue > pBar.high; + isSwitchedToBearish = iValue > iBar.high && + pValue < pBar.low; + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // TODO: we can also Add other Validations Here ... + + // + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractZigZagPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + double iValue = EMPTY_VALUE; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 1, // Number of Requirements ... + tmpZigZagBuffer // Buffer ... + ); + ArraySetAsSeries(tmpZigZagBuffer, true); + + // + // Read and Validate Value ... + iValue = tmpZigZagBuffer[0]; + has = NotEmptyZero(iValue); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Type ... + iType = + iValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : iValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Dir ... + iDir = + IsXVale(iType) + ? X_DIRECTION_BULLISH + : IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + return result; + } + + /** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ + int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + double hkLows[]; + bool has = false; + double hkOpens[]; + double hkHighs[]; + double hkCloses[]; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double up = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + count = ReadHKBars( + hkOpens, + hkHighs, + hkLows, + hkCloses, + i, + 1 // + ); + has = IsValidSize(count); + if (!has) + { + continue; + } + + // + // Initialized Start Bar ... + if (i == start) + { + // + startHKLow = hkLows[0]; + startHKOpen = hkOpens[0]; + startHKHigh = hkHighs[0]; + startHKClose = hkCloses[0]; + } + + // + // Check Direction ... + isBullish = hkOpens[0] < hkCloses[0]; + isBearish = hkOpens[0] > hkCloses[0]; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Calculate Requirements for Processing ... + up = isBullish + ? hkCloses[0] + : hkOpens[0]; + down = isBullish + ? hkOpens[0] + : hkCloses[0]; + body = MathAbs(up - down); + range = hkHighs[0] - hkLows[0]; + highShadow = hkHighs[0] - up; + lowShadow = down - hkLows[0]; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? hkHighs[0] + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? hkLows[0] + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = "XHK_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : "") + + "_" + ToXString(TimeToSeconds(zone.from)); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + SpecifiedClean(hkLows); + SpecifiedClean(hkOpens); + SpecifiedClean(hkHighs); + SpecifiedClean(hkCloses); + + // + 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 + // + ); + } + + // + // Upper MA ... + + // + double GetMABandUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maBandUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maBandUpperBuffer[barIndex]; + } + + // + int CopyMABandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maBandUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // Lower MA ... + + // + double GetMABandLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maBandLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maBandLowerBuffer[barIndex]; + } + + // + int CopyMABandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maBandLowerBuffer, + 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 Middle ... + + // + double GetFiboMiddle( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboMiddleBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboMiddleBuffer[barIndex]; + } + + // + int CopyFiboMiddle( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboMiddleBuffer, + 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 + // + ); + } + + // + // ZigZag ... + + // + double GetZigZag( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Calculate(barIndex); + SpecifiedClean(zigzagBuffer); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_LINE, + barIndex, + 1, + zigzagBuffer // + ); + + // + int count = ArraySize(zigzagBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return zigzagBuffer[barIndex]; + } + + // + int CopyZigZag( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + // Calculate(start); + SpecifiedClean(zigzagBuffer); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_LINE, + start, + 0, + zigzagBuffer // + ); + + // + // Copy Items ... + return Copy( + 0, + count, + zigzagBuffer, + 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 + // + ); + } + + // + // XHK ... + + // + // 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 + // + ); + } + + // + // XHK 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 + // + ); + } + + // + // XHK 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 + // + ); + } + + // + // XHK 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 + // + ); + } + + // + // XHK Color ... + + // + double GetHKColor( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkColorBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkColorBuffer[barIndex]; + } + + // + int CopyHKColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkColorBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XFIMAInputs mInputs; // Inputs ... + + // + // Buffers ... + // Define in Public ... + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + XFIMA_MA_FAST_LINE, + barIndex, + maxRequiredBars, + maFastBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_FAST_COLOR_LINE, + barIndex, + maxRequiredBars, + maFastColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_FAST_STATE_LINE, + barIndex, + maxRequiredBars, + maFastStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_SLOW_LINE, + barIndex, + maxRequiredBars, + maSlowBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_SLOW_COLOR_LINE, + barIndex, + maxRequiredBars, + maSlowColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_SLOW_STATE_LINE, + barIndex, + maxRequiredBars, + maSlowStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_BAND_UPPER_LINE, + barIndex, + maxRequiredBars, + maBandUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_BAND_LOWER_LINE, + barIndex, + maxRequiredBars, + maBandLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_SAR_COLOR_LINE, + barIndex, + maxRequiredBars, + sarColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_SAR_STATE_LINE, + barIndex, + maxRequiredBars, + sarStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_FIBO_UPPER_LINE, + barIndex, + maxRequiredBars, + fiboUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_FIBO_MIDDLE_LINE, + barIndex, + maxRequiredBars, + fiboMiddleBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_FIBO_LOWER_LINE, + barIndex, + maxRequiredBars, + fiboLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_LINE, + barIndex, + maxRequiredBars, + zigzagBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_SC_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_SC_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MC_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MC_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_LC_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_LC_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HC_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HC_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_HIGHS_LINE, + barIndex, + maxRequiredBars, + highsBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_HIGHS_TIME_LINE, + barIndex, + maxRequiredBars, + highsTimeBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_LOWS_LINE, + barIndex, + maxRequiredBars, + lowsBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_ZIGZAG_LOWS_TIME_LINE, + barIndex, + maxRequiredBars, + lowsTimeBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HK_OPEN_LINE, + barIndex, + maxRequiredBars, + hkOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HK_HIGH_LINE, + barIndex, + maxRequiredBars, + hkHighBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HK_LOW_LINE, + barIndex, + maxRequiredBars, + hkLowBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HK_CLOSE_LINE, + barIndex, + maxRequiredBars, + hkCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + XFIMA_HK_COLOR_LINE, + barIndex, + maxRequiredBars, + hkColorBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + maFastBuffer, + maxAllowed // + ); + + // + CleanupArray( + maFastColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + maFastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + maBandUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + maBandLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboMiddleBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + zigzagBuffer, + 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( + highsBuffer, + maxAllowed // + ); + + // + CleanupArray( + highsTimeBuffer, + maxAllowed // + ); + + // + CleanupArray( + lowsBuffer, + maxAllowed // + ); + + // + CleanupArray( + lowsTimeBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkColorBuffer, + maxAllowed // + ); + } + + // + // XHK Helper ... + + // + int ReadHKBars( + double &open[], + double &high[], + double &low[], + double &close[], + int barIndex = 0, + int count = 1 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + // Normalize ... + count = NormalizeInt(count, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + // Open ... + CopyBuffer( + mHandler, + XFIMA_HK_OPEN_LINE, + barIndex, + count, + open // + ); + + // + // High ... + CopyBuffer( + mHandler, + XFIMA_HK_HIGH_LINE, + barIndex, + count, + high // + ); + + // + // Low ... + CopyBuffer( + mHandler, + XFIMA_HK_LOW_LINE, + barIndex, + count, + low // + ); + + // + // Close ... + CopyBuffer( + mHandler, + XFIMA_HK_CLOSE_LINE, + barIndex, + count, + close // + ); + + // + ArraySetAsSeries(low, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(close, true); + + // + // Min Number of Array Sizes ... + result = MathMin(ArraySize(open), ArraySize(high)); + result = MathMin(result, ArraySize(close)); + result = MathMin(result, ArraySize(low)); + + // + return result; + } + + /** + * Validate HK Zone ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param validationLength: int, Validation Length of Zones ... + * @param breakValidLength: int, Break Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * + * @return ( bool ) + */ + bool ValidateHKZone( + XBoxZone &zone, + int validationLength = 1, + int breakValidLength = 3, + bool validateFakeBreakes = true // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + breakValidLength = NormalizeInt(breakValidLength, 2); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Requirements ... + double low[]; + double open[]; + double high[]; + int count = 0; + double close[]; + + // + int start = zone.FromIndex() + 1; + int end = start + validationLength; + + // + // Validate Before ... + for (int i = start; i < end; i++) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + i, + 1 // + ); + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low[0] > zone.lower + : high[0] < zone.upper; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = start; i < end; i++) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + i, + 1 // + ); + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low[0] > zone.lower + : high[0] < zone.upper; + if (!result) + { + // + // Check For Fake Breake ... + if (validateFakeBreakes && breakValidLength > 0) + { + // + result = i - 1 >= 0; + if (result) + { + // + for (int j = i - 1; j >= zone.ToIndex(); j--) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + j, + 1 // + ); + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? close[0] > zone.upper + : close[0] < zone.lower; + if (result) + { + // + result = MathAbs(j - i) <= breakValidLength; + if (result) + { + break; + } + } + } + } + } + + // + if (!result) + { + break; + } + } + } + } + + // + // Cleanup Resource ... + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + return result; + } + + // + int ReadMAValues( + double &fast[], + double &slow[], + double &upper[], + double &lower[], + int barIndex = 0, + int count = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(fast); + SpecifiedClean(slow); + SpecifiedClean(upper); + SpecifiedClean(lower); + + // + // Normalize ... + count = NormalizeInt(count, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + CopyBuffer( + mHandler, + XFIMA_MA_FAST_LINE, + barIndex, + count, + fast // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_SLOW_LINE, + barIndex, + count, + slow // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_BAND_UPPER_LINE, + barIndex, + count, + upper // + ); + + // + CopyBuffer( + mHandler, + XFIMA_MA_BAND_LOWER_LINE, + barIndex, + count, + lower // + ); + + // + ArraySetAsSeries(fast, true); + ArraySetAsSeries(slow, true); + ArraySetAsSeries(upper, true); + ArraySetAsSeries(lower, true); + + // + result = MathMin(ArraySize(fast), ArraySize(slow)); + result = MathMin(result, ArraySize(upper)); + result = MathMin(result, ArraySize(lower)); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy 2.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy 2.mq5 new file mode 100644 index 0000000..279edae --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy 2.mq5 @@ -0,0 +1,567 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCXFIMAEALib ... +// Description: XFIMAEA Library ... +// +// +// 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 XFIMAEA Library" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" + +// +// Definitions ... + +/** + * XFIMA Base Market Structure ... + * AnalyseMarket result ... + **/ +struct XFIMAMarketStructure +{ + // + XOHCL bar; // Spacified Start Bar for Analysing ... + XPatternAnalysis barAnalysis; // Structure Bar Pattern Analysis ... + + // + XPivotAnalysis pvAnalysis; // PV Pivot Analysis Result ... + XPivotAnalysis zgAnalysis; // ZG Pivot Analysis Result ... + + // + XPatternAnalysis barsAnalysis[]; // Anaysed Bars ... + + // + // Constructor ... + XFIMAMarketStructure() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + bar.Clean(); + barAnalysis.Clean(); + + // + pvAnalysis.Clean(); + zgAnalysis.Clean(); + XClean(barsAnalysis); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = bar.IsValid() && + barAnalysis.IsValid(); + + // + return result; + } + + // + // Collectors ... + + /** + * Collect Required Zones from Structure ... + * + * @param dest: XBoxZone, reference collection to holds result ... + * @param forDir: ENUM_X_DIRECTION, Specified Collectiong ones Direction ... + * @param containsOB: bool, Contains OB Zones ... + * @param containsFVG: bool, Contains FVG Zones ... + * + * @return ( int ) + */ + int CollectZones( + XBoxZone &dest[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + bool containsOB = false, + bool containsFVG = false // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + bool canCollectBullish = + IsXBullish(forDir) || + !HasDirection(forDir); + + // + bool canCollectBearish = + IsXBearish(forDir) || + !HasDirection(forDir); + + // + int count = 0; + XBoxZone tmpBox; + + // + // Check Analysis ... + + // + // XPV ... + has = pvAnalysis.IsValid(); + if (has) + { + // + // Support ... + tmpBox.Clean(); + has = pvAnalysis.HasSupportBox(tmpBox); + if (has && canCollectBullish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + + // + // Resistance ... + tmpBox.Clean(); + has = pvAnalysis.HasResistanceBox(tmpBox); + if (has && canCollectBearish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + } + + // + // XZG ... + has = zgAnalysis.IsValid(); + if (has) + { + // + // Support ... + tmpBox.Clean(); + has = zgAnalysis.HasSupportBox(tmpBox); + if (has && canCollectBullish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + + // + // Resistance ... + tmpBox.Clean(); + has = zgAnalysis.HasResistanceBox(tmpBox); + if (has && canCollectBearish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + } + + // + // Bar Patterns ... + has = HasChild(barsAnalysis); + if (has) + { + // + count = ArraySize(barsAnalysis); + for (int i = 0; i < count; i++) + { + // + // Support ... + has = barsAnalysis[i].IsSupport(); + if (has && canCollectBullish) + { + // + AddIfNotExists( + barsAnalysis[i].support, + dest // + ); + } + + // + // Resistance ... + has = barsAnalysis[i].IsResistance(); + if (has && canCollectBearish) + { + // + AddIfNotExists( + barsAnalysis[i].resistance, + dest // + ); + } + + // + // OB ... + if (containsOB) + { + // + has = barsAnalysis[i].IsOB(); + if (has) + { + // + has = (canCollectBullish && barsAnalysis[i].ob.IsBullish()) || + (canCollectBearish && barsAnalysis[i].ob.IsBearish()); + if (has) + { + // + AddIfNotExists( + barsAnalysis[i].ob, + dest // + ); + } + } + } + + // + // FVG ... + if (containsFVG) + { + has = barsAnalysis[i].IsFVG(); + if (has) + { + // + has = (canCollectBullish && barsAnalysis[i].fvg.IsBullish()) || + (canCollectBearish && barsAnalysis[i].fvg.IsBearish()); + if (has) + { + // + AddIfNotExists( + barsAnalysis[i].fvg, + dest // + ); + } + } + } + } + } + + // + result = ArraySize(dest); + has = IsValidSize(result); + if (has) + { + // + // Update To Time ... + // and also we Can Validate Zones Here ... + datetime cTime = TimeCurrent(); + for (int i = 0; i < result; i++) + { + dest[i].to = cTime; + } + } + + // + // Cleanup ... + tmpBox.Clean(); + + // + return result; + } + + // +}; + +struct XFIMAMarketStructureConfig +{ + // + // Props ... + + // + // Detector Flags ... + + // + bool analysePVPivots; // Analyse PV Pivots ... + bool analyseZGPivots; // Analyse ZG Pivots ... + + // + bool analyseBarPatterns; // Analyse Bar Patterns ... + + // + // Detector Configs ... + + // + int loopback; // Max Allowed Looping Back Length ... + int requiredPivots; // Required Extracted Pivots for Analysis ... + + // + int pvPivotsValidationLength; // PV Pivots Validation Length ... + double maCrossValidationDiffMultiplier; // a Point Distance to Validate MA Crosses ... + + // + XPatternAnalysisConfig barsAnalysisConfig; // Bars Analyser Config ... + + // + // Constructor ... + XFIMAMarketStructureConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Detector Flags ... + analysePVPivots = false; + analyseZGPivots = false; + analyseBarPatterns = false; + + // + // Configure Detectors ... + loopback = 0; + requiredPivots = 0; + pvPivotsValidationLength = 0; + maCrossValidationDiffMultiplier = 0; + + // + barsAnalysisConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Detector Flags ... + analysePVPivots = true; + analyseZGPivots = true; + analyseBarPatterns = true; + + // + // Configure Detectors ... + loopback = 200; + requiredPivots = 10; + pvPivotsValidationLength = 5; + maCrossValidationDiffMultiplier = 4; + + // + barsAnalysisConfig.Default(); + barsAnalysisConfig.FullPattern(); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + // Detector Flags ... + analysePVPivots = false; + analyseZGPivots = false; + analyseBarPatterns = false; + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + // Detector Flags ... + analysePVPivots = true; + analyseZGPivots = true; + analyseBarPatterns = true; + } + + // +}; + +/** + * Configure Market Structure Drawer ... + **/ +struct XFIMAMarketStructureDrawerConfig +{ + // + // Props ... + + // + bool drawPVAnalysis; + bool drawZGAnalysis; + bool drawBarsAnalysis; + + // + XPOIDrawConfig drawConfig; + XPivotAnalysisDrawConfig pivotAnalysisDrawConfig; + XPatternAnalysisDrawConfig barAnalysisDrawConfig; + + // + // Constructor ... + XFIMAMarketStructureDrawerConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + drawConfig.Clean(); + barAnalysisDrawConfig.Clean(); + pivotAnalysisDrawConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = true; + drawZGAnalysis = true; + drawBarsAnalysis = true; + + // + // Drawing Configs ... + drawConfig.Default(); + pivotAnalysisDrawConfig.Default(); + + // + barAnalysisDrawConfig.Default(); + barAnalysisDrawConfig.Full(); + XClean(barAnalysisDrawConfig.allowedDrawZones); + Add( + X_BAR_PATTERN_SUPPORT, + barAnalysisDrawConfig.allowedDrawZones); + Add( + X_BAR_PATTERN_RESISTANCE, + barAnalysisDrawConfig.allowedDrawZones); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + barAnalysisDrawConfig.Off(); + pivotAnalysisDrawConfig.Off(); + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + barAnalysisDrawConfig.Full(); + pivotAnalysisDrawConfig.Full(); + } + + void ApplyDrawConfig() + { + // + barAnalysisDrawConfig.drawConfig = drawConfig; + barAnalysisDrawConfig.ConfigureQuarterDraws(); + pivotAnalysisDrawConfig.drawConfig = drawConfig; + } + + void ApplyDrawConfig(XPOIDrawConfig &_drawConfig) + { + // + drawConfig = _drawConfig; + ApplyDrawConfig(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy.ex5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy.ex5 new file mode 100644 index 0000000..f2839dc Binary files /dev/null and b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy.ex5 differ diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy.mq5 new file mode 100644 index 0000000..78665e1 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib copy.mq5 @@ -0,0 +1,694 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCXFIMAEALib ... +// Description: XFIMAEA Library ... +// +// +// 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 XFIMAEA Library" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" + +// +// Definitions ... + +/** + * Configure Market Structure Detection ... + **/ +struct XFIMAPatternDetectorConfig +{ + // + // Props ... + + // + bool detectSwingTrend; + + // + bool detectStarPattern; + bool detectFlagPattern; + bool detectRisingPattern; + bool detectPiercingPattern; + bool detectSignalKeyBarPattern; + + // + bool detectPinned; + bool detectMomentum; + bool detectEngulfed; + bool detectTrueGaped; + + // + bool analyseFIMAPVPivots; + bool analyseFIMAZigZagPivots; + + // + bool detectMACrosses; + double validMACrossDiffMultiplier; + + // + bool detectHKSwitches; + bool detectSARSwitches; + + // + // Configs ... + + // + // Trending ... + int trendingNumberOfSwings; + int trendingSwingShoulders; + + // + // Support and Resistance ... + int zonesRequiredNumber; + int zonesValidationLength; + double zonesMinAlloweStrength; + int zonesBreakValidationLength; + double zonesBarShadowMultiplier; + int zonesMaxAllowedLoopbackLength; + + // + // TrueGap ... + double truwGapApprovedPointMultiplier; + + // + // Flag Pattern ... + int flagPatternMinimumPullbackBars; + + // + // Momentum Bar ... + int momentumBarRangeLength; + double momentumBarApprovedMultiplier; + + // + // Pinned Bar ... + double pinnedBaarShadowApprovedMultiplier; + double pinnedBarMinimumPinBarRangeMultiplier; + bool pinnedBarForceDirection; + + // + // SignalKey Bar ... + double signalKeyBarShadowApprovedMultiplier; + double signalKeyBarMinimumPinBarRangeMultiplier; + bool signalKeyBarForceDirection; + + // + // Analyser ... + int pvPivotsValidationLength; + int numberOfRequiredPivotsForAnalysis; + int maxAllowedLoopbackLengthForAnalysis; + + // + // Constructor ... + XFIMAPatternDetectorConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + detectSwingTrend = false; + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + analyseFIMAPVPivots = false; + detectPiercingPattern = false; + analyseFIMAZigZagPivots = false; + detectSignalKeyBarPattern = false; + + // + detectMACrosses = false; + validMACrossDiffMultiplier = 0; + + // + detectHKSwitches = false; + detectSARSwitches = false; + + // + zonesRequiredNumber = 0; + zonesValidationLength = 0; + zonesMinAlloweStrength = 0; + zonesBarShadowMultiplier = 0; + zonesBreakValidationLength = 0; + zonesMaxAllowedLoopbackLength = 0; + + // + trendingNumberOfSwings = 0; + trendingSwingShoulders = 0; + momentumBarRangeLength = 0; + pvPivotsValidationLength = 0; + pinnedBarForceDirection = false; + momentumBarApprovedMultiplier = 0; + signalKeyBarForceDirection = false; + truwGapApprovedPointMultiplier = 0; + flagPatternMinimumPullbackBars = 0; + numberOfRequiredPivotsForAnalysis = 0; + pinnedBaarShadowApprovedMultiplier = 0; + maxAllowedLoopbackLengthForAnalysis = 0; + signalKeyBarShadowApprovedMultiplier = 0; + pinnedBarMinimumPinBarRangeMultiplier = 0; + signalKeyBarMinimumPinBarRangeMultiplier = 0; + + // + ZeroMemory(this); + } + + /** + * Default Model ... + */ + void Default() + { + // + // Patterns ... + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + detectPiercingPattern = false; + detectSignalKeyBarPattern = false; + + // + // Bars ... + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + + // + // Analysers ... + analyseFIMAPVPivots = false; + analyseFIMAZigZagPivots = false; + + // + detectMACrosses = true; + validMACrossDiffMultiplier = 1; + + // + detectHKSwitches = true; + detectSARSwitches = true; + + // + // Trending ... + trendingNumberOfSwings = 3; + trendingSwingShoulders = 11; + + // + // Support and Resistance ... + zonesRequiredNumber = 25; + zonesValidationLength = 21; + zonesMinAlloweStrength = 2; + zonesBarShadowMultiplier = 4; + zonesBreakValidationLength = 3; + zonesMaxAllowedLoopbackLength = 200; + + // + // TrueGap ... + truwGapApprovedPointMultiplier = 1; + + // + // Flag Pattern ... + flagPatternMinimumPullbackBars = 3; + + // + // Momentum Bar ... + momentumBarRangeLength = 3; + momentumBarApprovedMultiplier = 2; + + // + // Pinned Bar ... + pinnedBaarShadowApprovedMultiplier = 3; + pinnedBarMinimumPinBarRangeMultiplier = 4; + pinnedBarForceDirection = false; + + // + // SignalKey Bar ... + signalKeyBarShadowApprovedMultiplier = 3; + signalKeyBarMinimumPinBarRangeMultiplier = 4; + signalKeyBarForceDirection = false; + + // + // Length ... + pvPivotsValidationLength = 10; + numberOfRequiredPivotsForAnalysis = 50; + maxAllowedLoopbackLengthForAnalysis = 1500; + } + + /** + * Full Detection Model ... + */ + void FullDetect() + { + // + // Patterns ... + detectStarPattern = true; + detectFlagPattern = true; + detectRisingPattern = true; + detectPiercingPattern = true; + detectSignalKeyBarPattern = true; + + // + // Bars ... + detectPinned = true; + detectMomentum = true; + detectEngulfed = true; + detectTrueGaped = true; + + // + // Analysers ... + analyseFIMAPVPivots = true; + analyseFIMAZigZagPivots = true; + + // + detectMACrosses = true; + detectHKSwitches = true; + detectSARSwitches = true; + } + + /** + * Default Config, by turn off all detecting flags ... + */ + void OffDetectors() + { + // + // Patterns ... + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + detectPiercingPattern = false; + detectSignalKeyBarPattern = false; + + // + // Bars ... + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + + // + // Analysers ... + analyseFIMAPVPivots = false; + analyseFIMAZigZagPivots = false; + + // + detectMACrosses = false; + detectHKSwitches = false; + detectSARSwitches = false; + } + + // +}; + +/** + * XFIMA Base Market Structure ... + * AnalyseMarket result ... + **/ +struct XFIMAMarketStructure +{ + // + XOHCL bar; + + // + XBoxZone obs[]; + XBoxZone fvgs[]; + XBoxZone supports[]; + XBoxZone resistances[]; + + // + XPivot pinBars[]; + XPivot engulfBars[]; + XPivot trueGapBars[]; + XPivot momentumBars[]; + + // + XBoxZone flagPatterns[]; + XBoxZone starPatterns[]; + XBoxZone risingPatterns[]; + XBoxZone piercingPatterns[]; + XBoxZone signalKeyBarPatterns[]; + + // + // Analysis ... + XPivotAnalysis pvAnalysis; + XPivotAnalysis zigzagAnalysis; + + // + ENUM_X_DIRECTION pinnedDir; + ENUM_X_DIRECTION momentumDir; + ENUM_X_DIRECTION engulfedDir; + ENUM_X_DIRECTION trueGapedDir; + + // + XOHCL flagSwing; + ENUM_X_DIRECTION flagPatternDir; + + // + XOHCL trendSwings[]; + ENUM_X_DIRECTION trendDir; + + // + ENUM_X_DIRECTION starPatternDir; + ENUM_X_DIRECTION risingPatternDir; + ENUM_X_DIRECTION piercingPatternDir; + ENUM_X_DIRECTION signalKeyBarPatternDir; + + // + ENUM_X_DIRECTION maCrossDir; + XPivot maCrosses[]; + + // + ENUM_X_DIRECTION hkSwitchDir; + XPivot hkSwitches[]; + + // + ENUM_X_DIRECTION sarSwitchDir; + XPivot sarSwitches[]; + + // + // Constructor ... + XFIMAMarketStructure() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + bar.Clean(); + flagSwing.Clean(); + + // + pvAnalysis.Clean(); + zigzagAnalysis.Clean(); + + // + trendDir = X_DIRECTION_NONE; + pinnedDir = X_DIRECTION_NONE; + momentumDir = X_DIRECTION_NONE; + engulfedDir = X_DIRECTION_NONE; + trueGapedDir = X_DIRECTION_NONE; + flagPatternDir = X_DIRECTION_NONE; + starPatternDir = X_DIRECTION_NONE; + risingPatternDir = X_DIRECTION_NONE; + piercingPatternDir = X_DIRECTION_NONE; + signalKeyBarPatternDir = X_DIRECTION_NONE; + + // + maCrossDir = X_DIRECTION_NONE; + SpecifiedClean(maCrosses); + + // + hkSwitchDir = X_DIRECTION_NONE; + SpecifiedClean(hkSwitches); + + // + sarSwitchDir = X_DIRECTION_NONE; + SpecifiedClean(sarSwitches); + + // + SpecifiedClean(obs); + SpecifiedClean(fvgs); + SpecifiedClean(pinBars); + SpecifiedClean(supports); + SpecifiedClean(engulfBars); + SpecifiedClean(resistances); + SpecifiedClean(trueGapBars); + SpecifiedClean(momentumBars); + SpecifiedClean(flagPatterns); + SpecifiedClean(starPatterns); + SpecifiedClean(risingPatterns); + SpecifiedClean(piercingPatterns); + SpecifiedClean(signalKeyBarPatterns); + + // + SpecifiedClean(trendSwings); + + // + ZeroMemory(this); + } + + // + // Checker Functions ... + + // +}; + +/** + * Configure Market Structure Drawer ... + **/ +struct XFIMAMarketStructureDrawerConfig +{ + // + // Props ... + + // + bool drawOB; // Current Order Block ... + bool drawFVG; // Current Fair Value Gap ... + + // + bool drawSupport; // Detected Supports ... + bool drawResistance; // Detected Resistances ... + + // + bool drawSwingTrend; // Swing Trend ... + bool swingTrendRayLeft; // Ray Left Swing Trend ... + bool swingTrendRayRight; // Ray Right Swing Trend ... + + // + // Draw Current Detected Patterns ... + + // + bool drawPinned; + bool drawMomentum; + bool drawEngulfed; + bool drawTrueGaped; + + // + bool drawStarPattern; + bool drawFlagPattern; + bool drawRisingPattern; + bool drawPiercingPattern; + bool drawSignalKeyBarPattern; + + // + // Draw Recently Zones ... + bool drawRecentPatterns; + bool drawFakeBreakedZone; + bool drawRecentlyTestedZones; + bool drawRecentlyBreakedZones; + + // + // Draw Analysis Pivots ... + + // + // XPV ... + bool drawFIMAPVPivotsAnalysis; + bool drawFIMAPVPivotsAnalysisZones; + bool drawFIMAPVPivotsAnalysisTrends; + bool drawFIMAPVPivotsAnalysisPivots; + + // + // XSAR ... + bool drawFIMASARPivotsAnalysis; + bool drawFIMASARPivotsAnalysisZones; + bool drawFIMASARPivotsAnalysisTrends; + bool drawFIMASARPivotsAnalysisPivots; + + // + // XZIGZAG ... + bool drawFIMAZigZagPivotsAnalysis; + bool drawFIMAZigZagPivotsAnalysisZones; + bool drawFIMAZigZagPivotsAnalysisTrends; + bool drawFIMAZigZagPivotsAnalysisPivots; + + // + // Constructor ... + XFIMAMarketStructureDrawerConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + drawOB = false; + drawFVG = false; + drawPinned = false; + drawMomentum = false; + drawSupport = false; + drawEngulfed = false; + drawTrueGaped = false; + drawResistance = false; + drawSwingTrend = false; + drawStarPattern = false; + drawFlagPattern = false; + swingTrendRayLeft = false; + drawRisingPattern = false; + swingTrendRayRight = false; + drawPiercingPattern = false; + drawSignalKeyBarPattern = false; + + // + drawRecentPatterns = false; + drawFakeBreakedZone = false; + drawRecentlyTestedZones = false; + drawRecentlyBreakedZones = false; + + // + drawFIMAPVPivotsAnalysis = false; + drawFIMAPVPivotsAnalysisZones = false; + drawFIMAPVPivotsAnalysisTrends = false; + drawFIMAPVPivotsAnalysisPivots = false; + + // + drawFIMASARPivotsAnalysis = false; + drawFIMASARPivotsAnalysisZones = false; + drawFIMASARPivotsAnalysisTrends = false; + drawFIMASARPivotsAnalysisPivots = false; + + // + drawFIMAZigZagPivotsAnalysis = false; + drawFIMAZigZagPivotsAnalysisZones = false; + drawFIMAZigZagPivotsAnalysisTrends = false; + drawFIMAZigZagPivotsAnalysisPivots = false; + + // + ZeroMemory(this); + } + + /** + * Default Model ... + */ + void Default() + { + drawOB = true; + drawFVG = true; + drawPinned = true; + drawMomentum = true; + drawSupport = true; + drawEngulfed = true; + drawTrueGaped = true; + drawResistance = true; + drawSwingTrend = true; + drawStarPattern = true; + drawFlagPattern = true; + drawRisingPattern = true; + drawPiercingPattern = true; + swingTrendRayLeft = false; + swingTrendRayRight = true; + drawSignalKeyBarPattern = true; + + // + drawRecentPatterns = true; + drawFakeBreakedZone = true; + drawRecentlyTestedZones = true; + drawRecentlyBreakedZones = true; + + // + drawFIMAPVPivotsAnalysis = true; + drawFIMAPVPivotsAnalysisZones = true; + drawFIMAPVPivotsAnalysisTrends = true; + drawFIMAPVPivotsAnalysisPivots = true; + + // + drawFIMASARPivotsAnalysis = true; + drawFIMASARPivotsAnalysisZones = true; + drawFIMASARPivotsAnalysisTrends = true; + drawFIMASARPivotsAnalysisPivots = true; + + // + drawFIMAZigZagPivotsAnalysis = true; + drawFIMAZigZagPivotsAnalysisZones = true; + drawFIMAZigZagPivotsAnalysisTrends = true; + drawFIMAZigZagPivotsAnalysisPivots = true; + } + + /** + * Configure for Full Drawing ... + */ + void FullDraw() + { + // + Default(); + + // + drawOB = true; + drawFVG = true; + drawPinned = true; + drawMomentum = true; + drawSupport = true; + drawEngulfed = true; + drawTrueGaped = true; + drawResistance = true; + drawSwingTrend = true; + drawStarPattern = true; + drawFlagPattern = true; + drawRisingPattern = true; + swingTrendRayLeft = true; + swingTrendRayRight = true; + drawPiercingPattern = true; + drawSignalKeyBarPattern = true; + + // + drawRecentPatterns = true; + drawFakeBreakedZone = true; + drawRecentlyTestedZones = true; + drawRecentlyBreakedZones = true; + + // + drawFIMAPVPivotsAnalysis = true; + drawFIMAPVPivotsAnalysisZones = true; + drawFIMAPVPivotsAnalysisTrends = true; + drawFIMAPVPivotsAnalysisPivots = true; + + // + drawFIMASARPivotsAnalysis = true; + drawFIMASARPivotsAnalysisZones = true; + drawFIMASARPivotsAnalysisTrends = true; + drawFIMASARPivotsAnalysisPivots = true; + + // + drawFIMAZigZagPivotsAnalysis = true; + drawFIMAZigZagPivotsAnalysisZones = true; + drawFIMAZigZagPivotsAnalysisTrends = true; + drawFIMAZigZagPivotsAnalysisPivots = true; + } + + // +}; diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib.ex5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib.ex5 new file mode 100644 index 0000000..adbfacf Binary files /dev/null and b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib.ex5 differ diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib.mq5 new file mode 100644 index 0000000..3a376c2 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.lib.mq5 @@ -0,0 +1,792 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCXFIMAEALib ... +// Description: XFIMAEA Library ... +// +// +// 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 XFIMAEA Library" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" + +// +// Definitions ... + +/** + * Configure Market Structure Detection ... + **/ +struct XFIMAPatternDetectorConfig +{ + // + // Props ... + + // + // Flags ... + + // + bool detectSupport; + bool detectResistance; + + // + bool detectSwingTrend; + + // + bool detectOB; + bool detectFVG; + + // + bool detectStarPattern; + bool detectFlagPattern; + bool detectRisingPattern; + bool detectPiercingPattern; + bool detectSignalKeyBarPattern; + + // + bool detectPinned; + bool detectMomentum; + bool detectEngulfed; + bool detectTrueGaped; + + // + bool analyseFIMAPVPivots; + bool analyseFIMASARPivots; + bool analyseFIMAZigZagPivots; + + // + bool detectMACrosses; + double validMACrossDiffMultiplier; + + // + bool detectHKSwitches; + bool detectSARSwitches; + + // + // Configs ... + + // + // OB / FVG ... + int obLoopback; + int fvgLoopback; + + // + // Trending ... + int trendingNumberOfSwings; + int trendingSwingShoulders; + + // + int recentlyPatternsMaxLookupLength; + int recentlyPatternsMaxAllowedCollecting; + + // + // Support and Resistance ... + int recentlyZonesMaxLookupLength; + int supportAndResistanceValidationLength; + int minAllowdSupportAndResistanceStrength; + int supportAndResistanceMaxAllowedLoopback; + int supportAndResistanceBreakeValidationLength; + + // + // TrueGap ... + double truwGapApprovedPointMultiplier; + + // + // Flag Pattern ... + int flagPatternMinimumPullbackBars; + + // + // Momentum Bar ... + int momentumBarRangeLength; + double momentumBarApprovedMultiplier; + + // + // Pinned Bar ... + double pinnedBaarShadowApprovedMultiplier; + double pinnedBarMinimumPinBarRangeMultiplier; + bool pinnedBarForceDirection; + + // + // SignalKey Bar ... + double signalKeyBarShadowApprovedMultiplier; + double signalKeyBarMinimumPinBarRangeMultiplier; + bool signalKeyBarForceDirection; + + // + // Analyser ... + int pvPivotsValidationLength; + int numberOfRequiredPivotsForAnalysis; + int maxAllowedLoopbackLengthForAnalysis; + + // + // Constructor ... + XFIMAPatternDetectorConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + detectOB = false; + detectFVG = false; + detectSupport = false; + detectResistance = false; + detectSwingTrend = false; + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + detectPiercingPattern = false; + detectSignalKeyBarPattern = false; + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + analyseFIMAPVPivots = false; + analyseFIMASARPivots = false; + analyseFIMAZigZagPivots = false; + + // + detectMACrosses = false; + validMACrossDiffMultiplier = 0; + + // + detectHKSwitches = false; + detectSARSwitches = false; + + // + obLoopback = 0; + fvgLoopback = 0; + trendingNumberOfSwings = 0; + trendingSwingShoulders = 0; + recentlyZonesMaxLookupLength = 0; + recentlyPatternsMaxLookupLength = 0; + recentlyPatternsMaxAllowedCollecting = 0; + supportAndResistanceValidationLength = 0; + minAllowdSupportAndResistanceStrength = 0; + supportAndResistanceMaxAllowedLoopback = 0; + supportAndResistanceBreakeValidationLength = 0; + truwGapApprovedPointMultiplier = 0; + flagPatternMinimumPullbackBars = 0; + momentumBarRangeLength = 0; + momentumBarApprovedMultiplier = 0; + pinnedBaarShadowApprovedMultiplier = 0; + pinnedBarMinimumPinBarRangeMultiplier = 0; + pinnedBarForceDirection = false; + signalKeyBarShadowApprovedMultiplier = 0; + signalKeyBarMinimumPinBarRangeMultiplier = 0; + signalKeyBarForceDirection = false; + pvPivotsValidationLength = 0; + numberOfRequiredPivotsForAnalysis = 0; + maxAllowedLoopbackLengthForAnalysis = 0; + + // + ZeroMemory(this); + } + + /** + * Default Model ... + */ + void Default() + { + // + // OB / FVG ... + detectOB = false; + detectFVG = false; + + // + // Support and Resistances ... + detectSupport = false; + detectResistance = false; + detectSwingTrend = false; + + // + // Patterns ... + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + detectPiercingPattern = false; + detectSignalKeyBarPattern = false; + + // + // Bars ... + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + + // + // Analysers ... + analyseFIMAPVPivots = false; + analyseFIMASARPivots = false; + analyseFIMAZigZagPivots = false; + + // + detectMACrosses = true; + validMACrossDiffMultiplier = 1; + + // + detectHKSwitches = true; + detectSARSwitches = true; + + // + // OB / FVg ... + obLoopback = 5; + fvgLoopback = 5; + + // + // Trending ... + trendingNumberOfSwings = 3; + trendingSwingShoulders = 11; + + // + // Support and Resistance ... + recentlyZonesMaxLookupLength = 100; + recentlyPatternsMaxLookupLength = 50; + recentlyPatternsMaxAllowedCollecting = 20; + supportAndResistanceValidationLength = 100; + minAllowdSupportAndResistanceStrength = 1; + supportAndResistanceMaxAllowedLoopback = 1500; + supportAndResistanceBreakeValidationLength = 4; + + // + // TrueGap ... + truwGapApprovedPointMultiplier = 1; + + // + // Flag Pattern ... + flagPatternMinimumPullbackBars = 3; + + // + // Momentum Bar ... + momentumBarRangeLength = 3; + momentumBarApprovedMultiplier = 2; + + // + // Pinned Bar ... + pinnedBaarShadowApprovedMultiplier = 3; + pinnedBarMinimumPinBarRangeMultiplier = 4; + pinnedBarForceDirection = false; + + // + // SignalKey Bar ... + signalKeyBarShadowApprovedMultiplier = 3; + signalKeyBarMinimumPinBarRangeMultiplier = 4; + signalKeyBarForceDirection = false; + + // + // Length ... + pvPivotsValidationLength = 10; + numberOfRequiredPivotsForAnalysis = 50; + maxAllowedLoopbackLengthForAnalysis = 1500; + } + + /** + * Full Detection Model ... + */ + void FullDetect() + { + // + // OB / FVG ... + detectOB = true; + detectFVG = true; + + // + // Support and Resistances ... + detectSupport = true; + detectResistance = true; + detectSwingTrend = true; + + // + // Patterns ... + detectStarPattern = true; + detectFlagPattern = true; + detectRisingPattern = true; + detectPiercingPattern = true; + detectSignalKeyBarPattern = true; + + // + // Bars ... + detectPinned = true; + detectMomentum = true; + detectEngulfed = true; + detectTrueGaped = true; + + // + // Analysers ... + analyseFIMAPVPivots = true; + analyseFIMASARPivots = true; + analyseFIMAZigZagPivots = true; + + // + detectMACrosses = true; + detectHKSwitches = true; + detectSARSwitches = true; + } + + /** + * Default Config, by turn off all detecting flags ... + */ + void OffDetectors() + { + // + // OB / FVG ... + detectOB = false; + detectFVG = false; + + // + // Support and Resistances ... + detectSupport = false; + detectResistance = false; + detectSwingTrend = false; + + // + // Patterns ... + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + detectPiercingPattern = false; + detectSignalKeyBarPattern = false; + + // + // Bars ... + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + + // + // Analysers ... + analyseFIMAPVPivots = false; + analyseFIMASARPivots = false; + analyseFIMAZigZagPivots = false; + + // + detectMACrosses = false; + detectHKSwitches = false; + detectSARSwitches = false; + } + + // +}; + +/** + * XFIMA Base Market Structure ... + * AnalyseMarket result ... + **/ +struct XFIMAMarketStructure +{ + // + XOHCL bar; + + // + XBoxZone ob; + XBoxZone fvg; + XBoxZone support; + XBoxZone resistance; + + // + XBoxZone obs[]; + XBoxZone fvgs[]; + XBoxZone supports[]; + XBoxZone resistances[]; + + // + XPivot pinBars[]; + XPivot engulfBars[]; + XPivot trueGapBars[]; + XPivot momentumBars[]; + + // + XBoxZone flagPatterns[]; + XBoxZone starPatterns[]; + XBoxZone risingPatterns[]; + XBoxZone piercingPatterns[]; + XBoxZone signalKeyBarPatterns[]; + + // + // Previous Support or Resistance based on current ... + // + // Current Support is Touched => Prev Support; + // Current Resistance is Touched => Prev Resistance; + XBoxZone fakeBreakedZone; + + // + XBoxZone recentlyTestedZones[]; + XBoxZone recentlyBreakedZones[]; + + // + // Analysis ... + XPivotAnalysis pvAnalysis; + XPivotAnalysis sarAnalysis; + XPivotAnalysis zigzagAnalysis; + + // + ENUM_X_DIRECTION pinnedDir; + ENUM_X_DIRECTION momentumDir; + ENUM_X_DIRECTION engulfedDir; + ENUM_X_DIRECTION trueGapedDir; + + // + XOHCL flagSwing; + ENUM_X_DIRECTION flagPatternDir; + + // + XOHCL trendSwings[]; + ENUM_X_DIRECTION trendDir; + + // + ENUM_X_DIRECTION starPatternDir; + ENUM_X_DIRECTION risingPatternDir; + ENUM_X_DIRECTION piercingPatternDir; + ENUM_X_DIRECTION signalKeyBarPatternDir; + + // + ENUM_X_DIRECTION maCrossDir; + XPivot maCrosses[]; + + // + ENUM_X_DIRECTION hkSwitchDir; + XPivot hkSwitches[]; + + // + ENUM_X_DIRECTION sarSwitchDir; + XPivot sarSwitches[]; + + // + // Constructor ... + XFIMAMarketStructure() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + ob.Clean(); + fvg.Clean(); + support.Clean(); + resistance.Clean(); + + // + fakeBreakedZone.Clean(); + + // + bar.Clean(); + flagSwing.Clean(); + + // + pvAnalysis.Clean(); + sarAnalysis.Clean(); + zigzagAnalysis.Clean(); + + // + trendDir = X_DIRECTION_NONE; + pinnedDir = X_DIRECTION_NONE; + momentumDir = X_DIRECTION_NONE; + engulfedDir = X_DIRECTION_NONE; + trueGapedDir = X_DIRECTION_NONE; + flagPatternDir = X_DIRECTION_NONE; + starPatternDir = X_DIRECTION_NONE; + risingPatternDir = X_DIRECTION_NONE; + piercingPatternDir = X_DIRECTION_NONE; + signalKeyBarPatternDir = X_DIRECTION_NONE; + + // + maCrossDir = X_DIRECTION_NONE; + SpecifiedClean(maCrosses); + + // + hkSwitchDir = X_DIRECTION_NONE; + SpecifiedClean(hkSwitches); + + // + sarSwitchDir = X_DIRECTION_NONE; + SpecifiedClean(sarSwitches); + + // + SpecifiedClean(obs); + SpecifiedClean(fvgs); + SpecifiedClean(pinBars); + SpecifiedClean(supports); + SpecifiedClean(engulfBars); + SpecifiedClean(resistances); + SpecifiedClean(trueGapBars); + SpecifiedClean(momentumBars); + SpecifiedClean(flagPatterns); + SpecifiedClean(starPatterns); + SpecifiedClean(risingPatterns); + SpecifiedClean(piercingPatterns); + SpecifiedClean(signalKeyBarPatterns); + + // + SpecifiedClean(trendSwings); + SpecifiedClean(recentlyTestedZones); + SpecifiedClean(recentlyBreakedZones); + + // + ZeroMemory(this); + } + + // + // Checker Functions ... + + // +}; + +/** + * Configure Market Structure Drawer ... + **/ +struct XFIMAMarketStructureDrawerConfig +{ + // + // Props ... + + // + bool drawOB; // Current Order Block ... + bool drawFVG; // Current Fair Value Gap ... + + // + bool drawSupport; // Detected Supports ... + bool drawResistance; // Detected Resistances ... + + // + bool drawSwingTrend; // Swing Trend ... + bool swingTrendRayLeft; // Ray Left Swing Trend ... + bool swingTrendRayRight; // Ray Right Swing Trend ... + + // + // Draw Current Detected Patterns ... + + // + bool drawPinned; + bool drawMomentum; + bool drawEngulfed; + bool drawTrueGaped; + + // + bool drawStarPattern; + bool drawFlagPattern; + bool drawRisingPattern; + bool drawPiercingPattern; + bool drawSignalKeyBarPattern; + + // + // Draw Recently Zones ... + bool drawRecentPatterns; + bool drawFakeBreakedZone; + bool drawRecentlyTestedZones; + bool drawRecentlyBreakedZones; + + // + // Draw Analysis Pivots ... + + // + // XPV ... + bool drawFIMAPVPivotsAnalysis; + bool drawFIMAPVPivotsAnalysisZones; + bool drawFIMAPVPivotsAnalysisTrends; + bool drawFIMAPVPivotsAnalysisPivots; + + // + // XSAR ... + bool drawFIMASARPivotsAnalysis; + bool drawFIMASARPivotsAnalysisZones; + bool drawFIMASARPivotsAnalysisTrends; + bool drawFIMASARPivotsAnalysisPivots; + + // + // XZIGZAG ... + bool drawFIMAZigZagPivotsAnalysis; + bool drawFIMAZigZagPivotsAnalysisZones; + bool drawFIMAZigZagPivotsAnalysisTrends; + bool drawFIMAZigZagPivotsAnalysisPivots; + + // + // Constructor ... + XFIMAMarketStructureDrawerConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + drawOB = false; + drawFVG = false; + drawPinned = false; + drawMomentum = false; + drawSupport = false; + drawEngulfed = false; + drawTrueGaped = false; + drawResistance = false; + drawSwingTrend = false; + drawStarPattern = false; + drawFlagPattern = false; + swingTrendRayLeft = false; + drawRisingPattern = false; + swingTrendRayRight = false; + drawPiercingPattern = false; + drawSignalKeyBarPattern = false; + + // + drawRecentPatterns = false; + drawFakeBreakedZone = false; + drawRecentlyTestedZones = false; + drawRecentlyBreakedZones = false; + + // + drawFIMAPVPivotsAnalysis = false; + drawFIMAPVPivotsAnalysisZones = false; + drawFIMAPVPivotsAnalysisTrends = false; + drawFIMAPVPivotsAnalysisPivots = false; + + // + drawFIMASARPivotsAnalysis = false; + drawFIMASARPivotsAnalysisZones = false; + drawFIMASARPivotsAnalysisTrends = false; + drawFIMASARPivotsAnalysisPivots = false; + + // + drawFIMAZigZagPivotsAnalysis = false; + drawFIMAZigZagPivotsAnalysisZones = false; + drawFIMAZigZagPivotsAnalysisTrends = false; + drawFIMAZigZagPivotsAnalysisPivots = false; + + // + ZeroMemory(this); + } + + /** + * Default Model ... + */ + void Default() + { + drawOB = true; + drawFVG = true; + drawPinned = true; + drawMomentum = true; + drawSupport = true; + drawEngulfed = true; + drawTrueGaped = true; + drawResistance = true; + drawSwingTrend = true; + drawStarPattern = true; + drawFlagPattern = true; + drawRisingPattern = true; + drawPiercingPattern = true; + swingTrendRayLeft = false; + swingTrendRayRight = true; + drawSignalKeyBarPattern = true; + + // + drawRecentPatterns = true; + drawFakeBreakedZone = true; + drawRecentlyTestedZones = true; + drawRecentlyBreakedZones = true; + + // + drawFIMAPVPivotsAnalysis = true; + drawFIMAPVPivotsAnalysisZones = true; + drawFIMAPVPivotsAnalysisTrends = true; + drawFIMAPVPivotsAnalysisPivots = true; + + // + drawFIMASARPivotsAnalysis = true; + drawFIMASARPivotsAnalysisZones = true; + drawFIMASARPivotsAnalysisTrends = true; + drawFIMASARPivotsAnalysisPivots = true; + + // + drawFIMAZigZagPivotsAnalysis = true; + drawFIMAZigZagPivotsAnalysisZones = true; + drawFIMAZigZagPivotsAnalysisTrends = true; + drawFIMAZigZagPivotsAnalysisPivots = true; + } + + /** + * Configure for Full Drawing ... + */ + void FullDraw() + { + // + Default(); + + // + drawOB = true; + drawFVG = true; + drawPinned = true; + drawMomentum = true; + drawSupport = true; + drawEngulfed = true; + drawTrueGaped = true; + drawResistance = true; + drawSwingTrend = true; + drawStarPattern = true; + drawFlagPattern = true; + drawRisingPattern = true; + swingTrendRayLeft = true; + swingTrendRayRight = true; + drawPiercingPattern = true; + drawSignalKeyBarPattern = true; + + // + drawRecentPatterns = true; + drawFakeBreakedZone = true; + drawRecentlyTestedZones = true; + drawRecentlyBreakedZones = true; + + // + drawFIMAPVPivotsAnalysis = true; + drawFIMAPVPivotsAnalysisZones = true; + drawFIMAPVPivotsAnalysisTrends = true; + drawFIMAPVPivotsAnalysisPivots = true; + + // + drawFIMASARPivotsAnalysis = true; + drawFIMASARPivotsAnalysisZones = true; + drawFIMASARPivotsAnalysisTrends = true; + drawFIMASARPivotsAnalysisPivots = true; + + // + drawFIMAZigZagPivotsAnalysis = true; + drawFIMAZigZagPivotsAnalysisZones = true; + drawFIMAZigZagPivotsAnalysisTrends = true; + drawFIMAZigZagPivotsAnalysisPivots = true; + } + + // +}; diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy 2.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy 2.mq5 new file mode 100644 index 0000000..b2d9299 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy 2.mq5 @@ -0,0 +1,2249 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + bool ignoreTargets; // Ignore Signal Targets ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + /** + * Check Specified Bar has Pattern or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param name: string, reference to holds Detected Patterns Name ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Patterns Direction ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool HasPattern( + XOHCL &bar, + string &patternName, + ENUM_X_DIRECTION &patternDir, + XFIMAMarketStructure &structure // + ) + { + // + bool result = false; + + // + // Prepare ... + patternName = NULL; + patternDir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + result = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + + // + if (result) + { + // + if (hasPinnedBar) + { + // + patternDir = structure.pinnedDir; + patternName = "XPinned_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + patternDir = structure.engulfedDir; + patternName = "XEngulfed_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + patternDir = structure.flagPatternDir; + patternName = "XFlag_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + patternDir = structure.starPatternDir; + patternName = "XStar_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + patternDir = structure.risingPatternDir; + patternName = "XRising_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + patternDir = structure.piercingPatternDir; + patternName = "XPiercing_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + patternDir = structure.signalKeyBarPatternDir; + patternName = "XSignalKey_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + } + + // + result = + result && + IsXValid(patternName) && + HasDirection(patternDir); + + // + return result; + } + + /** + * Validate a Pattern based on MA Band ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param patternName: string, detected pattern's name ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool ValidatePatternBasedOnMABand( + XOHCL &bar, + string patternName, + ENUM_X_DIRECTION patternDir, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + // Calculating Price and Price Types ... + + // + isBullish = IsXBullish(patternDir); + isBearish = IsXBearish(patternDir); + + // + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + + // + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate ... + result = + NotEmptyZero(iPrice) && + IsXValid(iPriceType) && + NotEmptyZero(iPriceEdge) && + IsXValid(iPriceEdgeType) && + ((isBullish && !isBearish) || + (isBearish && !isBullish)); + if (!result) + { + return result; + } + + // + // Validate Pattern based on MA Band ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBondUpperBuffer[0]; + double iMABandLower = fimaConditions.maBondLowerBuffer[0]; + + // + // Validate by Edge Price ... + result = + NotEmptyZero(iMABandUpper) && + NotEmptyZero(iMABandLower) && + (isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + CArrayObj drawnObjects; + // XFIMAPatternDetectorConfig analyserConfig; + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure Detector ... + + // + analyserConfig.Default(); + analyserConfig.validMACrossDiffMultiplier = 4; + + // + analyserConfig.FullDetect(); + + // + // Ignore Signal Targets ... + ignoreTargets = true; + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + + // + analyserConfig.Clean(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + int count = 0; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + string iName = NULL; + bool isBullish = false; + bool isBearish = false; + XPatternAnalysis iBarAnalysis; + XFIMAConditions iFIMAConditions; + XFIMAMarketStructure iStructure; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + iFIMAConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + iBar.Clean(); + iFIMAConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + iBar, + iStructure, + analyserConfig // + ); + + // + // Bar Pattern Analysis Detection Test ... + has = poiDetector.AnalyseBarPatterns( + iBar, + iBarAnalysis + // + // Use Default Config ... + ); + DrawBarPatternAnalysis(iBarAnalysis); + + // + // Disable Signallers ... + has = false; + iDir = X_DIRECTION_NONE; + + // + // Strategy 1 ... + // Works on Support or Resistances Areas ... + // has = Strategy1HasSignal( + // iBar, + // iZone, + // iTargets, + // iDir, + // iFIMAConditions, + // iStructure // + // ); + + // + // Strategy 2 ... + // Works on MA Crosses ... + if (!has) + { + // + // has = Strategy2HasSignal( + // iBar, + // iZone, + // iTargets, + // iDir, + // iFIMAConditions, + // iStructure // + // ); + } + + // + has = HasDirection(iDir); + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // TODO: Provided SL ... + double _point = GetPoints(iBar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + + // + // Handle Signal Targets ... + if (ignoreTargets) + { + XClean(iTargets); + } + + // + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(iSignal); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + iStructure.Clean(); + iBarAnalysis.Clean(); + iFIMAConditions.Clean(); + SpecifiedClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir, + XFIMAConditions &conditions, + XFIMAMarketStructure &structure // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Pattern Exists ... + string patternName = NULL; + ENUM_X_DIRECTION patternDir = X_DIRECTION_NONE; + result = HasPattern( + bar, + patternName, + patternDir, + structure // + ); + if (!result) + { + return result; + } + + // + // Validate Pattern Based on MA Band ... + result = ValidatePatternBasedOnMABand( + bar, + patternName, + patternDir, + conditions // + ); + if (!result) + { + return result; + } + + // + // Here i Use Specified Supports and Resistances ... + XBoxZone tmpBox; + bool has = false; + XBoxZone supports[]; + XBoxZone resistances[]; + + // + has = structure.pvAnalysis.IsValid() && + structure.pvAnalysis.HasSupportBox(tmpBox); + if (has) + { + // + tmpBox.to = bar.time; + AddIfNotExists( + tmpBox, + supports // + ); + } + + // + has = structure.zigzagAnalysis.IsValid() && + structure.zigzagAnalysis.HasSupportBox(tmpBox); + if (has) + { + // + tmpBox.to = bar.time; + AddIfNotExists( + tmpBox, + supports // + ); + } + + // + has = structure.pvAnalysis.IsValid() && + structure.pvAnalysis.HasResistanceBox(tmpBox); + if (has) + { + // + tmpBox.to = bar.time; + AddIfNotExists( + tmpBox, + resistances // + ); + } + + // + has = structure.zigzagAnalysis.IsValid() && + structure.zigzagAnalysis.HasResistanceBox(tmpBox); + if (has) + { + // + tmpBox.to = bar.time; + AddIfNotExists( + tmpBox, + resistances // + ); + } + + // + // Check Affected Zone ... + // Select a Support or Resistance ... + int insideZoneIDX = -1; + result = + (IsXBullish(patternDir) + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : IsXBearish(patternDir) + ? HasInside( + insideZoneIDX, + bar, + resistances // + ) + : false // + ); + if (!result) + { + return result; + } + + // + // Filling Affected Zone ... + // and Validate it ... + if (IsXBullish(patternDir)) + { + zone = supports[insideZoneIDX]; + } + else if (IsXBearish(patternDir)) + { + zone = resistances[insideZoneIDX]; + } + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Validate affected Zone based on Pattern's Bar ... + result = IsXBullish(patternDir) + ? bar.high > zone.upper + : IsXBearish(patternDir) + ? bar.low < zone.lower + : false; + // + // Validate Zone ... + if (result) + { + // + // + } + + // + // Draw Requirements ... + // if (result) + // { + // // + // // Support and Resistances ... + // CArrayObj *zoneObjs; + // poiDrawer.DrawBoxes( + // supports, + // zoneObjs // + // ); + // poiDrawer.DrawBoxes( + // resistances, + // zoneObjs // + // ); + + // // + // // Zone ... + // XCBoxObject *iZoneObj; + // bool isDrawn = poiDrawer.DrawBox( + // zone, + // iZoneObj, + // true, + // zone.type // + // ); + // if (isDrawn) + // { + // // + // XPOIStyle iStyle; + // iStyle.width = 2; + // iStyle.clr = clrYellow; + // poiDrawer.ApplyBoxStyle( + // iZoneObj, + // iStyle // + // ); + // } + + // // + // // Pattern ... + // XCBarArrowObject *iPObj; + // poiDrawer.DrawBarArrow( + // bar, + // iPObj, + // zone.IsBullish() ? X_PRICE_LOW : X_PRICE_HIGH, + // 159, + // clrYellow, + // 3, // With ... + // zone.IsBullish() ? ANCHOR_BOTTOM : ANCHOR_TOP, + // patternName // + // ); + + // // poiDrawer.DrawBoxes( + // // structure.fvgs, + // // zoneObjs, + // // false // + // // ); + + // Print("SALAM"); + // } + + if (result) + { + // + dir = patternDir; + + // + // Handle Targets Detection ... + + // + // Check Reversal FVGS ... + int idx = -1; + XTarget target; + XBoxZone targetZones[]; + int numberOfTargets = 3; + double actingDistance = 20; + double iValue = EMPTY_VALUE; + bool ignoreFirstTarget = false; + ENUM_X_DIRECTION targetsDir = Opposit(dir); + int count = ExtractByDirection( + targetZones, + structure.fvgs, + targetsDir // + ); + bool has = IsValidSize(count); + if (has) + { + // + // Calculate Value ... + double points = GetPoints(zone.symbol); + double zoneRange = zone.upper - zone.lower; + iValue = IsXBullish(dir) + ? (zone.upper + (zoneRange * defaultSignalR2R)) + : (zone.lower + (zoneRange * defaultSignalR2R)); + double defaultTarget = iValue; + + // + // Looping Back ... + for (int i = 0; i < numberOfTargets; i++) + { + // + // Detect Lowest Above Zone ... + if (IsXBullish(dir)) + { + // + idx = GetLowestAbove(iValue, targetZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + iValue = targetZones[idx].lower; + } + // + // Detect Highest below Zone ... + else if (IsXBearish(dir)) + { + // + idx = GetHighestBelow(iValue, targetZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + iValue = targetZones[idx].upper; + } + + // + // Validate Target Value ... + has = NotEmptyZero(iValue) && + iValue != defaultTarget; + if (has) + { + // + // Init Target ... + target.Clean(); + target.doRF = true; + target.target = iValue; + target.actingDistance = actingDistance; + has = target.IsValid(); + if (has) + { + // + // Add Target to Targets ... + AddRef( + target, + targets // + ); + } + target.Clean(); + } + } + + // + // Remove Nearest ... + has = ignoreFirstTarget && + HasChild(targets); + if (has) + { + // + ArrayRemove( + targets, + 0, + 1 // + ); + } + } + + // + // Cleanup Resources ... + target.Clean(); + XClean(targetZones); + } + + // + // Cleanup Resources ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + } + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir, + XFIMAConditions &conditions, + XFIMAMarketStructure &structure // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Detect Specified MA Cross ... + result = HasDirection(structure.maCrossDir); + + // + // Prepare zone ... + if (result) + { + // + zone.to = bar.time; + zone.from = GetBarTime( + bar.symbol, + bar.period, + bar.Index() + 2 // + ); + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.dir = structure.maCrossDir; + zone.lower = bar.FindLowest(2, MODE_LOW); + zone.upper = bar.FindHighest(2, MODE_HIGH); + zone.type = name + "_" + ToXString(structure.maCrossDir); + + // + result = zone.IsValid(); + } + + // + // Check Result ... + if (result) + { + // + dir = structure.maCrossDir; + + // + // Handle Targets Detection ... + } + + // + // Cleanup Resources ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + } + + // + return result; + } + + // + // Drawer Functions ... + + /** + * Draw Specified Pattern info ... + * + * @param _bar: XOHCL, reference to Pattern's Bar ... + * @param _pivot: XPivot, reference to Pattern's Pivot ... + * @param _zone: XBoxZone, reference to Pattern's Zone ... + * @param _pattern: ENUM_X_BAR_PATTERN, Specified Bar Pattern ... + * @param _patternDir: ENUM_X_DIRECTION, Specified Bar Pattern's Direction ... + */ + void DrawPattern( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_BAR_PATTERN _pattern, + ENUM_X_DIRECTION _patternDir, + int thresholdMultiplier = 0 // + ) + { + // + // Normalize ... + thresholdMultiplier = NormalizeInt(thresholdMultiplier, 1); + + // + // Validate ... + bool has = + poiDrawer != NULL && + _bar.IsValid() && + IsXValid(_pattern) && + HasDirection(_patternDir); + if (!has) + { + return; + } + + // + // Defien Draw Requirements ... + + // + int width = 3; + bool ignoreBoxAt = true; + int arrowThreshold = 5 * thresholdMultiplier; + + // + int bullishArrow = 159; + int bearishArrow = 159; + + // + ENUM_X_PRICE arrowValePriceType = X_PRICE_LOW; + ENUM_X_PRICE arrowPeakPriceType = X_PRICE_HIGH; + + // + color bullishColor = clrAqua; + color bearishColor = clrMagenta; + + // + // Draw Bar ... + + // + // Draw Pivot ... + if (_pivot.IsValid()) + { + // + XCBarArrowObject *iObj; + has = poiDrawer.DrawBarArrow( + _bar, + iObj, + _pivot.IsPeak() + ? arrowPeakPriceType + : arrowValePriceType, + IsXBullish(_patternDir) + ? bullishArrow + : bearishArrow, + IsXBullish(_patternDir) + ? bullishColor + : bearishColor, + width, + IsXBullish(_patternDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM, + _pivot.prefix + "_Pivot_" + ToXString(TimeToSeconds(_pivot.time)), + true, // Ignore Bar Tag ... + arrowThreshold // Threshold ... + ); + if (has) + { + drawnObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Draw Box ... + if (_zone.IsValid()) + { + // + XCBoxObject *iObj; + has = poiDrawer.DrawBox( + _zone, + iObj, + ignoreBoxAt, + _zone.type + "_Zone_" + ToXString(TimeToSeconds(_zone.from)) // + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + _zone.dir // + ); + + // + iStyle.clr = + IsXBullish(_patternDir) + ? bullishColor + : bearishColor; + + // + poiDrawer.ApplyBoxStyle( + iObj, + iStyle // + ); + + // + drawnObjects.Add(iObj); + + // + iStyle.Clean(); + } + + // + ZeroMemory(iObj); + } + } + + /** + * Draw Specified Bar Pattern Analysis ... + * + * @param barAnalysis: XPatternAnalysis, reference to Specified Bar Pattern Analysis ... + */ + void DrawBarPatternAnalysis(XPatternAnalysis &barAnalysis) + { + // + bool has = barAnalysis.IsValid(); + if (!has) + { + return; + } + + // + // Configure Draws ... + XPatternAnalysisDrawConfig config; + config.Clean(); + + // + Add(X_BAR_PATTERN_LOW, config.allowedDraws); + Add(X_BAR_PATTERN_HIGH, config.allowedDraws); + Add(X_BAR_PATTERN_STAR, config.allowedDraws); + Add(X_BAR_PATTERN_FLAG, config.allowedDraws); + Add(X_BAR_PATTERN_PINNED, config.allowedDraws); + Add(X_BAR_PATTERN_RISING, config.allowedDraws); + Add(X_BAR_PATTERN_MOMENTUM, config.allowedDraws); + Add(X_BAR_PATTERN_ENGULFED, config.allowedDraws); + Add(X_BAR_PATTERN_PIERCING, config.allowedDraws); + Add(X_BAR_PATTERN_SIGNALKEY, config.allowedDraws); + Add(X_BAR_PATTERN_TRUE_GAPED, config.allowedDraws); + + // + Add(X_BAR_PATTERN_LOW, config.allowedDrawPivots); + Add(X_BAR_PATTERN_HIGH, config.allowedDrawPivots); + Add(X_BAR_PATTERN_PINNED, config.allowedDrawPivots); + Add(X_BAR_PATTERN_MOMENTUM, config.allowedDrawPivots); + Add(X_BAR_PATTERN_ENGULFED, config.allowedDrawPivots); + Add(X_BAR_PATTERN_TRUE_GAPED, config.allowedDrawPivots); + + // + Add(X_BAR_PATTERN_STAR, config.allowedDrawZones); + Add(X_BAR_PATTERN_FLAG, config.allowedDrawZones); + Add(X_BAR_PATTERN_RISING, config.allowedDrawZones); + Add(X_BAR_PATTERN_PIERCING, config.allowedDrawZones); + Add(X_BAR_PATTERN_SIGNALKEY, config.allowedDrawZones); + + // + Add(X_BAR_PATTERN_SUPPORT, config.allowedDraws); + Add(X_BAR_PATTERN_RESISTANCE, config.allowedDraws); + + // + Add(X_BAR_PATTERN_SUPPORT, config.allowedDrawZones); + Add(X_BAR_PATTERN_RESISTANCE, config.allowedDrawZones); + + // + config.Clean(); + + // + // Draw Bar Patterns Analysis ... + + // + bool canDraw; + bool isBullish; + bool isBearish; + XOHCL patternBar; + bool canDrawZone; + bool canDrawPivot; + XPivot patternPivot; + XBoxZone patternBox; + ENUM_X_BAR_PATTERN pattern; + ENUM_X_DIRECTION patternDir; + + // + int patternsPivotThresholdMultiplier = 0; + + // + // Support and Resistance ... + + // + // Support ... + isBearish = false; + isBullish = barAnalysis.IsSupport(); + has = isBullish; + if (has) + { + // + pattern = X_BAR_PATTERN_SUPPORT; + patternDir = X_DIRECTION_BULLISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Resistance ... + isBullish = false; + isBearish = barAnalysis.IsResistance(); + has = isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_RESISTANCE; + patternDir = X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // PV: High and Low ... + + // + // Low ... + isBearish = false; + isBullish = barAnalysis.IsLow(); + has = isBullish; + if (has) + { + // + pattern = X_BAR_PATTERN_LOW; + patternDir = X_DIRECTION_BULLISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // High ... + isBullish = false; + isBearish = barAnalysis.IsHigh(); + has = isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_HIGH; + patternDir = X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // OB ... + isBullish = barAnalysis.IsOB(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsOB(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_OB; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // FVG ... + isBullish = barAnalysis.IsFVG(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsFVG(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_FVG; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Momentum ... + isBullish = barAnalysis.IsMomentum(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsMomentum(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_MOMENTUM; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Engulfed ... + isBullish = barAnalysis.IsEngulfed(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsEngulfed(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_ENGULFED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Pinned ... + isBullish = barAnalysis.IsPinned(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsPinned(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_PINNED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // TrueGaped ... + isBullish = barAnalysis.IsTrueGaped(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsTrueGaped(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_TRUE_GAPED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Star ... + isBullish = barAnalysis.IsStar(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsStar(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_STAR; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Piercing ... + isBullish = barAnalysis.IsPiercing(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsPiercing(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_PIERCING; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Rising ... + isBullish = barAnalysis.IsRising(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsRising(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_RISING; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Flag ... + isBullish = barAnalysis.IsFlag(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsFlag(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_FLAG; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // SignalKey ... + isBullish = barAnalysis.IsSignalKey(X_DIRECTION_BULLISH); + isBearish = barAnalysis.IsSignalKey(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_SIGNALKEY; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + canDraw = config.CanDraw(pattern); + if (canDraw) + { + // + has = barAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + canDrawZone = config.CanDrawZone(pattern); + if (!canDrawZone) + { + patternBox.Clean(); + } + + // + canDrawPivot = config.CanDrawPivot(pattern); + if (!canDrawPivot) + { + patternPivot.Clean(); + } + else + { + patternsPivotThresholdMultiplier++; + } + + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir, + patternsPivotThresholdMultiplier // + ); + } + } + } + + // + // Cleanup Resources ... + patternBar.Clean(); + patternBox.Clean(); + patternPivot.Clean(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy 3.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy 3.mq5 new file mode 100644 index 0000000..b29a2e5 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy 3.mq5 @@ -0,0 +1,1657 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + bool ignoreTargets; // Ignore Signal Targets ... + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + XFIMAMarketStructure structure; // XFIMA Market Structure ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + + // + structure.Clean(); + + // + // Ignore Signal Targets ... + ignoreTargets = false; + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + + // + structure.Clean(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + int count = 0; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + string iName = NULL; + bool isBullish = false; + bool isBearish = false; + XFIMAConditions iFIMAConditions; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + iFIMAConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + iBar.Clean(); + iFIMAConditions.Clean(); + + // + return; + } + + // + structure.Clean(); + poiDetector.AnalyseMarket( + structure, + structureConfig, + barIndex // + ); + // poiDrawer.drawnObjects.Clear(); + // poiDrawer.DrawMarketStructure( + // structure, + // structureDrawConfig // + // ); + + // + // Strategy 1 ... + // has = Strategy1HasSignal( + // iBar, + // iZone, + // iTargets, + // iDir, + // iFIMAConditions, + // structure // + // ); + + // + // Strategy 2 ... + if (!has) + { + // // + // has = Strategy2HasSignal( + // iBar, + // iZone, + // iTargets, + // iDir, + // iFIMAConditions, + // structure // + // ); + } + + // + // Strategy 3 ... + if (!has) + { + // + // has = Strategy3HasSignal( + // iBar, + // iZone, + // iTargets, + // iDir, + // iFIMAConditions, + // structure // + // ); + } + + // + // Strategy 4 ... + has = false; + if (!has) + { + // + has = Strategy4HasSignal( + iBar, + iZone, + iTargets, + iDir, + iFIMAConditions, + structure // + ); + } + + // + has = HasDirection(iDir) && + iZone.IsValid(); + if (has) + { + // + has = false; + iZone.Clean(); + iDir = X_DIRECTION_NONE; + } + + // + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // TODO: Provided SL ... + double _point = GetPoints(iBar.symbol); + double slAddition = 5 * _point; + double atrAddition = GetAverageTrueRange( + iZone.symbol, + iZone.period, + 0 // + ); + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + + // + // Handle Signal Targets ... + if (ignoreTargets) + { + XClean(iTargets); + } + + // + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(iSignal); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + iFIMAConditions.Clean(); + SpecifiedClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir, + XFIMAConditions &conditions, + XFIMAMarketStructure &_structure // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Testing Porposes ... + result = + result && + fimaHelper.IsBoundaryFakeBreaked( + dir, + bar.Index(), + X_PRICE_CLOSE, + X_PRICE_CLOSE // + ); + + // + // Nearest Noisy ZG Pivot Must has Same Direction + // by Boundary Faked Break ... + result = + result && + HasDirection(dir) && + _structure.zgAnalysis.IsValid() && + _structure.zgAnalysis.HasPivots() && + _structure.zgAnalysis.pivots[0].dir == dir; + + // + // We Have to Detect a Zone which Nearest ZG Pivot Reject or goes inside it ... + + // + int idx = -1; + XOHCL tmpBar; + XPivot pivot; + XPivot pivots[]; + XBoxZone zones[]; + bool has = false; + int zonesCount = 0; + int pivotIndex = -1; + XBoxZone affectedZone; + double bullishScore = 0; + double bearishScore = 0; + int prevPivotIndex = -1; + XBoxZone affectedZones[]; + int affectedZonesCount = 0; + + // + Copy( + _structure.zgAnalysis.pivots, + pivots // + ); + pivot = pivots[0]; + ArrayRemove(pivots, 0, 1); + + // + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + zonesCount = _structure.CollectZones( + zones, + dir // + ); + result = result && + IsValidSize(zonesCount); + + // + // Noisey ZG Pivot must inside atleast one of Zones ... + + // + // Initial Pivots Bar ... + result = + result && + bar.BarAt(pivot.time, tmpBar); + + // + // Extract Affected Zones ... + if (result) + { + // + affectedZonesCount = ExtractAffectedZones( + tmpBar, + zones, + affectedZones, + dir // + ); + } + + // + // Validate Affected Zones ... + result = + result && + HasChild(affectedZones) && + affectedZonesCount >= 1; + if (result) + { + affectedZone = affectedZones[0]; + } + result = + result && + affectedZone.IsValid() && + (isBullish + ? bar.close > affectedZone.upper + : bar.close < affectedZone.lower); + + // + // There Must another Same Directional ZG Pivot Exists + // which is Affect another Zone ... + idx = GetYoungest(pivots, pivot.type); + result = + result && + IsValidIndex(idx) && + affectedZone.IsValid() && + (isBullish + ? pivots[idx].value < pivot.value + : pivots[idx].value > pivot.value); + if (result) + { + // + pivot.Clean(); + tmpBar.Clean(); + pivot = pivots[idx]; + XClean(affectedZones); + ArrayRemove(pivots, idx, 1); + + // + result = bar.BarAt(pivot.time, tmpBar); + } + + // + // Extract Affected Zones ... + XClean(affectedZones); + affectedZonesCount = 0; + if (result) + { + // + affectedZonesCount = ExtractAffectedZones( + tmpBar, + zones, + affectedZones, + dir // + ); + } + result = + result && + HasChild(affectedZones) && + affectedZonesCount >= 1; + + // + // Handling Scores ... + if (result) + { + // + for (int i = 0; i < ArraySize(_structure.barsAnalysis); i++) + { + // + bullishScore += _structure.barsAnalysis[i].Count(X_DIRECTION_BULLISH); + bearishScore += _structure.barsAnalysis[i].Count(X_DIRECTION_BEARISH); + } + } + result = + isBullish + ? bullishScore > bearishScore + : bearishScore > bullishScore; + + // + // Last Validation is Candlestick Patterns of Bar ... + // XPatternAnalysis barAnalysis; + // result = + // result && + // poiDetector.AnalyseBarPatterns( + // bar, + // barAnalysis, + // structureConfig.barsAnalysisConfig // + // ); + + // + if (!result) + { + // + dir = X_DIRECTION_NONE; + + // + return result; + } + + // + // Drawa ... + if (result) + { + // + // Affected Zone ... + XCBoxObject *iObj; + has = poiDrawer.DrawBox( + affectedZone, + iObj, + true, + affectedZone.type + "_" + ToXString(TimeToSeconds(affectedZone.from)) // + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + affectedZone.dir // + ); + iStyle.clr = clrYellow; + poiDrawer.ApplyBoxStyle( + iObj, + iStyle // + ); + iStyle.Clean(); + + // + Print("Affected Zone ..."); + } + + // + // Draw Bar Pattern ... + // poiDrawer.DrawPatternAnalysis(barAnalysis, structureDrawConfig.barAnalysisDrawConfig); + } + + // + // Prepare zone ... + if (result) + { + // + zone = affectedZone; + + // + zone.type = name + "_" + ToXString(dir); + + // + double entry = GetEntry(bar.symbol, dir); + double points = GetPoints(bar.symbol); + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)); + double reward = risk * defaultSignalR2R; + + // + // Partially Close on TP 1 ... + double tp1 = isBullish + ? entry + (risk * 1) + : entry - (risk * 1); + XTarget target1; + target1.target = tp1; + target1.doRF = false; + target1.actingDistance = 2; + target1.volumeMultiplier = 0.5; + + // + // TP 3 ... + double tp3 = isBullish + ? entry + (risk * 3) + : entry - (risk * 3); + XTarget target3; + target3.target = tp3; + target3.doRF = true; + target3.actingDistance = 10; + + // + // TP 5 ... + double tp5 = isBullish + ? entry + (risk * 5) + : entry - (risk * 5); + XTarget target5; + target5.target = tp5; + target5.doRF = true; + target5.actingDistance = 10; + + // + AddRef( + target1, + targets // + ); + AddRef( + target3, + targets // + ); + AddRef( + target5, + targets // + ); + + // + result = zone.IsValid(); + } + + // + // Check Result ... + if (result) + { + // + // dir = structure.maCrossDir; + + // + // Handle Targets Detection ... + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + } + + // + pivot.Clean(); + XClean(zones); + tmpBar.Clean(); + XClean(pivots); + affectedZone.Clean(); + XClean(affectedZones); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir, + XFIMAConditions &conditions, + XFIMAMarketStructure &_structure // + ) + { + // + bool result = false; + + // + // Prepare ... + XOHCL pBar; + XOHCL p2Bar; + zone.Clean(); + pBar.Clean(); + p2Bar.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid() && + bar.GetPreviousBar(pBar) && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + return result; + } + + // + result = false; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION tmpDir; + + // + // Do Signal Detection ... + + // + // Preparing Requirement Conditions ... + // Here we Have to Prepare Some Directional Confirmations Using Indicators ... + // for Validate Signals ... + + // + int verifierBarIndex = pBar.Index(); + + // + bool hasSarSwitch = fimaHelper.HasSARSwitch(tmpDir, verifierBarIndex); + bool isSarSwitchedToBullish = hasSarSwitch && + IsXBullish(tmpDir); + bool isSarSwitchedToBearish = hasSarSwitch && + IsXBearish(tmpDir); + + // + bool hasMACross = fimaHelper.HasMACross( + tmpDir, + verifierBarIndex, + structureConfig.maCrossValidationDiffMultiplier // + ); + bool isCrossedOver = hasMACross && + IsXBullish(tmpDir); + bool isCrossedUnder = hasMACross && + IsXBearish(tmpDir); + + // + bool hasHKSwitch = fimaHelper.HasHKSwitch(tmpDir, verifierBarIndex); + bool isHKSwitchedToBullish = hasHKSwitch && + IsXBullish(tmpDir); + bool isHKSwitchedToBearish = hasHKSwitch && + IsXBearish(tmpDir); + + // + bool isBoundaryFakeBreaked = fimaHelper.IsBoundaryFakeBreaked(tmpDir, verifierBarIndex); + bool isBoundaryFakeBreakedBullish = isBoundaryFakeBreaked && + IsXBullish(tmpDir); + bool isBoundaryFakeBreakedBearish = isBoundaryFakeBreaked && + IsBearish(tmpDir); + + // + bool hasZigZagHigherLow = fimaHelper.HasZigZagHigherLow(bar.Index(), true); + bool hasZigZagLowerHigh = fimaHelper.HasZigZagLowerHigh(bar.Index(), true); + + // + // Summarize Confirmations ... + + // + bool isBullishConfirmed = + (hasZigZagHigherLow && + ( + // + isCrossedOver || + isHKSwitchedToBullish || + isSarSwitchedToBullish || + isBoundaryFakeBreakedBullish + // + )); + + // + bool isBearishConfirmed = + (hasZigZagLowerHigh && + ( + // + isCrossedUnder || + isHKSwitchedToBearish || + isSarSwitchedToBearish || + isBoundaryFakeBreakedBullish + // + )); + + // + // Validation Patterns ... + int directionalPatternsValidations = 3; + + // + // Check Bullish Conditions ... + isBullish = + // + // Confirmations Passed ... + isBullishConfirmed && + // + // Quarters Has Minor Support Zone ... + _structure.barAnalysis.HasMinorSupport() && + // + // Current Bar's Price Placed Propper ... + bar.open > _structure.barAnalysis.minorSupport.upper && + bar.close > _structure.barAnalysis.minorSupport.upper && + // + // Required Number of Pivots Validation Exists ... + (_structure.barsAnalysis[1].Count(X_DIRECTION_BULLISH) >= directionalPatternsValidations) && + // + // Bar or PBar ReTested Quarter Zone ... + (IsTested( + pBar, + _structure.barAnalysis.minorSupport // + ) || + IsTested( + p2Bar, + _structure.barAnalysis.minorSupport // + )) + // + ; + + // + // Check Bearish Conditions ... + isBearish = + // + // Confirmations Passed ... + isBearishConfirmed && + // + // Quarters Has Minor Resistance Zone ... + _structure.barAnalysis.HasMinorResistance() && + // + // Current Bar's Price Placed Propper ... + bar.open < _structure.barAnalysis.minorResistance.lower && + bar.close < _structure.barAnalysis.minorResistance.lower && + // + // Required Number of Pivots Validation Exists ... + (_structure.barsAnalysis[1].Count(X_DIRECTION_BEARISH) >= directionalPatternsValidations) && + // + // Bar or pBar ReTested Quarter Zone ... + (IsTested( + pBar, + _structure.barAnalysis.minorResistance // + ) || + IsTested( + p2Bar, + _structure.barAnalysis.minorResistance // + )) + // + ; + + // + // Summarize Conditions ... + result = + isBullish || + isBearish; + + // + // Assign Direction ... + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + if (isBullish) + { + zone = _structure.barAnalysis.minorSupport; + } + + // + if (isBearish) + { + zone = _structure.barAnalysis.minorResistance; + } + } + + // + // Validate Result ... + result = + result && + zone.IsValid() && + HasDirection(dir); + // if (result) + // { + // // + // XPOIDrawConfig iConfig = structureDrawConfig + // .barAnalysisDrawConfig + // .quarterMinorsDrawConfig; + // iConfig.zonesWidth = 3; + // iConfig.zonesFill = true; + // iConfig.bullishColor = clrYellow; + // iConfig.bearishColor = clrYellow; + + // // + // if (isBullish) + // { + // // + // poiDrawer.DrawZone( + // _structure.barAnalysis.minorSupport, + // iConfig // + // ); + + // // + // Print("Bullish Condition ..."); + // } + + // // + // if (isBearish) + // { + // // + // poiDrawer.DrawZone( + // _structure.barAnalysis.minorResistance, + // iConfig // + // ); + + // // + // Print("Bearish Condition ..."); + // } + + // // + // Print(ToXString(dir), " Detected ..."); + // } + + // + // Provide Direction and Targets if Required ... + if (result) + { + // + // Handle Targets Detection ... + + // + double spread = GetSpread(zone.symbol); + double entry = GetEntry(zone.symbol, dir); + + // + double risk = isBullish + ? entry - zone.lower + : zone.upper - entry; + double reward1 = entry + (isBullish + ? risk + : (-1 * risk) // + ); + double reward4 = entry + (isBullish + ? 4 * risk + : (-4 * risk) // + ); + double requiredDistance = PriceToPoint(spread * 2, zone.symbol); + + // + XTarget iRFOnEntryOnTP1; + iRFOnEntryOnTP1.target = reward1; + iRFOnEntryOnTP1.tpValue = reward4; + iRFOnEntryOnTP1.doRFOnEntry = true; + iRFOnEntryOnTP1.volumeMultiplier = 0.5; + iRFOnEntryOnTP1.actingDistance = requiredDistance; + + // + AddRef( + iRFOnEntryOnTP1, + targets // + ); + } + + // + // Cleanup Resources ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir, + XFIMAConditions &conditions, + XFIMAMarketStructure &_structure // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + + // + XOHCL pBar; + int barIndex = bar.Index(); + int pBarIndex = barIndex + 1; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Do Conditions Checking ... + + // + XBoxZone zones[]; + int zonesCount = 0; + ENUM_X_PRICE bullishPriceType = X_PRICE_LOW; + ENUM_X_PRICE bearishPriceType = X_PRICE_HIGH; + + // + isBullish = fimaHelper.IsSwitchedUnderHKBondLower(bullishPriceType, pBarIndex); + + // + isBearish = fimaHelper.IsSwitchedOverHKBondUpper(bearishPriceType, pBarIndex); + + // + result = + isBullish || + isBearish; + + // + // Do Validations ... + if (result) + { + // + // Direction Assignment ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + int lastIDX; + XBoxZone tmpZones[]; + int tmpZonesCount = 0; + int validationCount = 0; + ENUM_X_PRICE priceType = + isBullish + ? bullishPriceType + : bearishPriceType; + + // + // Detect Last Direction Change ... + if (isBullish) + { + result = fimaHelper.FindLastUnderHKBondLower(lastIDX, bullishPriceType, pBarIndex); + } + else + { + result = fimaHelper.FindLastOverHKBondUpper(lastIDX, bearishPriceType, pBarIndex); + } + + // + // Validate Direction Changed ... + if (result) + { + // + validationCount = lastIDX - pBarIndex; + result = validationCount >= 10; + } + + // + // Collect Zones ... + if (result) + { + // + // Support and Resistances ... + tmpZonesCount = poiDetector.CollectZones( + pBar, + tmpZones, + 5, + 14, // Zones Validation Length ... + 0, // Required Count ... + validationCount // Loopback ... + ); + if (IsValidSize(tmpZonesCount)) + { + // + Copy( + tmpZones, + zones, + false // ignore Clean ... + ); + } + + // + // OB ... + tmpZonesCount = poiDetector.CollectOBs( + pBar, + tmpZones, + 5, // Zones Loopback ... + 0, // Required Count ... + validationCount // Loopback ... + ); + if (IsValidSize(tmpZonesCount)) + { + // + Copy( + tmpZones, + zones, + false // ignore Clean ... + ); + } + + // + // FVG ... + tmpZonesCount = poiDetector.CollectFVGs( + pBar, + tmpZones, + 5, // Zones Loopback ... + 0, // Required Count ... + validationCount // Loopback ... + ); + if (IsValidSize(tmpZonesCount)) + { + // + Copy( + tmpZones, + zones, + false // ignore Clean ... + ); + } + + // + // Filter Zones Based on pBar ... + zonesCount = poiDetector.FilterZones( + pBar, + zones, + dir, + priceType, + dir // + ); + + // + // Extract Affected Zones ... + XClean(tmpZones); + tmpZonesCount = ExtractAffectedZones( + pBar, + zones, + tmpZones, + dir // + ); + Copy(tmpZones, zones); + zonesCount = ArraySize(zones); + + // + // Update Zones Time ... + UpdateToTime(zones); + } + + // + // Draw Zones ... + result = IsValidSize(zonesCount); + if (result) + { + // + for (int i = 0; i < zonesCount; i++) + { + poiDrawer.DrawZone(zones[i], structureDrawConfig.drawConfig); + } + } + + // + XClean(tmpZones); + } + + // + // Prepare Zone ... + if (result) + { + // + // Zone Detection ... + zone.Clean(); + if (isBullish) + { + // + int idx = GetLowest(zones); + if (IsValidIndex(idx)) + { + zone = zones[idx]; + } + } + else + { + // + int idx = GetHighest(zones); + if (IsValidIndex(idx)) + { + zone = zones[idx]; + } + } + + // zone.dir = dir; + // zone.type = name; + // zone.to = bar.time; + // zone.at = pBar.time; + // zone.from = pBar.time; + // zone.symbol = bar.symbol; + // zone.period = bar.period; + // zone.lower = MathMin(pBar.low, bar.low); + // zone.upper = MathMax(pBar.high, bar.high); + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + // Target Handling ... + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + XClean(zones); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir, + XFIMAConditions &conditions, + XFIMAMarketStructure &_structure // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + + // + XOHCL pBar; + int barIndex = bar.Index(); + int pBarIndex = barIndex + 1; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Do Conditions Checking ... + + // + // Reading HK Bond ... + double hkBondUpper = fimaHelper.GetHKBondUpper(pBarIndex); + double hkBondLower = fimaHelper.GetHKBondLower(pBarIndex); + bool hasHKBoundary = + NotEmptyZero(hkBondUpper) && + NotEmptyZero(hkBondLower); + + // + // Pullback Detection ... + bool isPullback = poiDetector.IsPullbackPattern( + pBar, + zone, + dir, + 2, + false // + ); + + // + isBullish = + isPullback && + hasHKBoundary && + IsXBullish(dir) && + zone.lower > hkBondLower; + + // + isBearish = + isPullback && + hasHKBoundary && + IsXBearish(dir) && + zone.upper < hkBondUpper; + + // + result = + isBullish || + isBearish; + + // + // Do Validations ... + if (result) + { + // + // Direction Assignment ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // TEMP ... + poiDrawer.DrawZone( + zone, + structureDrawConfig.drawConfig // + ); + } + + // + // Prepare Decision Zone ... + if (result) + { + // + // Zone Detection ... + zone.Clean(); + + // + // zone.dir = dir; + // zone.type = name; + // zone.to = bar.time; + // zone.at = pBar.time; + // zone.from = pBar.time; + // zone.symbol = bar.symbol; + // zone.period = bar.period; + // zone.lower = MathMin(pBar.low, bar.low); + // zone.upper = MathMax(pBar.high, bar.high); + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + // Target Handling ... + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy.mq5 new file mode 100644 index 0000000..89475e9 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class copy.mq5 @@ -0,0 +1,1697 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + /** + * Check Specified Bar has Pattern or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param name: string, reference to holds Detected Patterns Name ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Patterns Direction ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool HasPattern( + XOHCL &bar, + string &patternName, + ENUM_X_DIRECTION &patternDir, + XFIMAMarketStructure &structure // + ) + { + // + bool result = false; + + // + // Prepare ... + patternName = NULL; + patternDir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + result = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + + // + if (result) + { + // + if (hasPinnedBar) + { + // + patternDir = structure.pinnedDir; + patternName = "XPinned_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + patternDir = structure.engulfedDir; + patternName = "XEngulfed_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + patternDir = structure.flagPatternDir; + patternName = "XFlag_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + patternDir = structure.starPatternDir; + patternName = "XStar_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + patternDir = structure.risingPatternDir; + patternName = "XRising_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + patternDir = structure.piercingPatternDir; + patternName = "XPiercing_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + patternDir = structure.signalKeyBarPatternDir; + patternName = "XSignalKey_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); + } + } + + // + result = + result && + IsXValid(patternName) && + HasDirection(patternDir); + + // + return result; + } + + /** + * Validate a Pattern based on MA Band ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param patternName: string, detected pattern's name ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool ValidatePatternBasedOnMABand( + XOHCL &bar, + string patternName, + ENUM_X_DIRECTION patternDir, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + // Calculating Price and Price Types ... + + // + isBullish = IsXBullish(patternDir); + isBearish = IsXBearish(patternDir); + + // + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + + // + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate ... + result = + NotEmptyZero(iPrice) && + IsXValid(iPriceType) && + NotEmptyZero(iPriceEdge) && + IsXValid(iPriceEdgeType) && + ((isBullish && !isBearish) || + (isBearish && !isBullish)); + if (!result) + { + return result; + } + + // + // Validate Pattern based on MA Band ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBandUpperBuffer[0]; + double iMABandLower = fimaConditions.maBandLowerBuffer[0]; + + // + // Validate by Edge Price ... + result = + NotEmptyZero(iMABandUpper) && + NotEmptyZero(iMABandLower) && + (isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 1 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + fvgLookupLenght = 5; + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL bar; + XSignal signal; + bool has = false; + int cIdx = barIndex + 1; + int pIdx = cIdx + 1; + ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + cIdx // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + XFIMAConditions fimaConditions; + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Conditions for Finding Signal ... + + // + // TODO: Remove this ... + + // + bool isFastCrossedOverSlow = + fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] && + fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx]; + + // + bool isFastCrossedUnderSlow = + fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] && + fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx]; + + // + has = + isFastCrossedOverSlow || + isFastCrossedUnderSlow; + if (has) + { + // + // Do Conditions Validating ... + // TODO: Igmore All Validations for Testing Purposes ... + + // + // Validate MA Positions ... + double iFastMa = fimaConditions.maFastBuffer[cIdx]; + double iSlowMa = fimaConditions.maSlowBuffer[cIdx]; + double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx]; + double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx]; + + // + // Checking Has FVG ... + XBoxZone fvg; + ENUM_X_DIRECTION fvgDir; + bool hasFVG = patternDetector.HasFVG( + bar, + fvgDir, + fvg, + fvgLookupLenght // + ); + + // + // Checking Crossed On Shadow ... + + // + bool isCrossedOverHappensOnShadow = + isFastCrossedOverSlow && + iFastMa <= bar.GetDown() && + iFastMa >= bar.low; + + // + bool isCrossedUnderHappensOnShadow = + isFastCrossedUnderSlow && + iFastMa <= bar.high && + iFastMa >= bar.GetUp(); + + // + // Bullish Validation ... + bool isBullish = + // + // Has Cross ... + isFastCrossedOverSlow + // + // && + // // + // // Cross Places Based on Fibo ... + // MathMax(iFastMa, iSlowMa) < iFiboLower + // // + // && + // // + // ( + // // + // // Checking FVG ... + // (hasFVG && + // fvg.IsBullish()) + // // + // || + // // + // // Checking Crossed Place ... + // isCrossedOverHappensOnShadow + // // + // ) + // // + ; + + // + // Bearish Validation ... + bool isBearish = + // + // Has Cross ... + isFastCrossedUnderSlow + // + // && + // // + // // Cross Places Based on Fibo ... + // MathMin(iFastMa, iSlowMa) > iFiboUpper + // // + // && + // // + // ( + // // + // // Checking FVG ... + // (hasFVG && + // fvg.IsBearish()) + // // + // || + // // + // // Checking Crossed Place ... + // isCrossedUnderHappensOnShadow + // // + // ) + // // + ; + + // + has = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (has) + { + // + signalDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + + // + // Check Signal Founded ... + has = HasDirection(signalDir); + if (has) + { + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + signalDir, + targets // + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + signal.Clean(); + fimaConditions.Clean(); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Lookup FVG ... + bool LookupFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvgBox // + ) + { + // + bool result = false; + + // + return result; + } + + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + XFIMAPatternDetectorConfig analyserConfig; + + // + // Constructor ... + XCXFIMAStrategy2Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA2", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure Detector ... + // + analyserConfig.Default(); + analyserConfig.validMACrossDiffMultiplier = 4; + + // + analyserConfig.FullDetect(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy2Signaller() + { + // + Destroy(); + + // + analyserConfig.Clean(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + int count = 0; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget targets[]; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + int numberOfPivots = 25; + XFIMAConditions iFIMAConditions; + XFIMAMarketStructure iStructure; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + iFIMAConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + iBar.Clean(); + iFIMAConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + iBar, + iStructure, + analyserConfig // + ); + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = iStructure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = iStructure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = iBar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = iStructure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = iBar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + numberOfPivots // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = iStructure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = iStructure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = iBar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = iStructure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = iBar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + numberOfPivots // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = iStructure.support.IsValid(); + if (hasSupport) + { + // + iStructure.support.to = iBar.time; + AddIfNotExists( + iStructure.support, + supports // + ); + } + + // + // Resistance ... + bool hasResistance = iStructure.resistance.IsValid(); + if (hasResistance) + { + // + iStructure.resistance.to = iBar.time; + AddIfNotExists( + iStructure.resistance, + resistances // + ); + } + + // + // Disable Signallers ... + has = false; + + // + // Strategy 1 ... + // Works on Support or Resistances Areas ... + // has = Strategy1HasSignal( + // iBar, + // iZone, + // supports, + // resistances, + // iDir, + // iStructure, + // iFIMAConditions // + // ); + + // + // Strategy 2 ... + // Works on MA Crosses ... + has = Strategy2HasSignal( + iBar, + iZone, + supports, + resistances, + iDir, + iStructure, + iFIMAConditions // + ); + + // + has = HasDirection(iDir); + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // TODO: Provided SL ... + double _point = GetPoints(iBar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + has = PrepareSignal( + iSignal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(iSignal); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + iStructure.Clean(); + iFIMAConditions.Clean(); + SpecifiedClean(targets); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param iDir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &iZone, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION &iDir, + XFIMAMarketStructure &structure, + XFIMAConditions &conditions // + ) + { + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + iDir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Pattern Exists ... + string patternName = NULL; + ENUM_X_DIRECTION patternDir = X_DIRECTION_NONE; + result = HasPattern( + bar, + patternName, + patternDir, + structure // + ); + if (!result) + { + return result; + } + + // + // Validate Pattern Based on MA Band ... + result = ValidatePatternBasedOnMABand( + bar, + patternName, + patternDir, + conditions // + ); + if (!result) + { + return result; + } + + // + // Check Affected Zone ... + // Select a Support or Resistance ... + int insideZoneIDX = -1; + result = + (IsXBullish(patternDir) + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : IsXBearish(patternDir) + ? HasInside( + insideZoneIDX, + bar, + resistances // + ) + : false // + ); + if (!result) + { + return result; + } + + // + // Filling Affected Zone ... + // and Validate it ... + if (IsXBullish(patternDir)) + { + iZone = supports[insideZoneIDX]; + } + else if (IsXBearish(patternDir)) + { + iZone = resistances[insideZoneIDX]; + } + result = iZone.IsValid(); + if (!result) + { + return result; + } + + // + // Validate affected Zone based on Pattern's Bar ... + result = IsXBullish(patternDir) + ? bar.high > iZone.upper + : IsXBearish(patternDir) + ? bar.low < iZone.lower + : false; + if (result) + { + iDir = patternDir; + } + + // + // Cleanup Resources ... + if (!result) + { + iZone.Clean(); + } + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param iDir: ENUM_X_DIRECTION, detected Signal's direction ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &iZone, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION &iDir, + XFIMAMarketStructure &structure, + XFIMAConditions &conditions // + ) + { + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + iDir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Detect Specified MA Cross ... + result = HasDirection(structure.maCrossDir); + + // + // Validate Conditions ... + + // + // Prepare iZone ... + iZone.to = bar.time; + iZone.from = GetBarTime( + bar.symbol, + bar.period, + bar.Index() + 2 // + ); + iZone.symbol = bar.symbol; + iZone.period = bar.period; + iZone.dir = structure.maCrossDir; + iZone.lower = bar.FindLowest(2, MODE_LOW); + iZone.upper = bar.FindHighest(2, MODE_HIGH); + iZone.type = name + "_" + ToXString(structure.maCrossDir); + + // + // Check Result ... + result = iZone.IsValid(); + if (result) + { + iDir = structure.maCrossDir; + } + + // + // Cleanup Resources ... + if (!result) + { + iZone.Clean(); + } + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class.mq5 new file mode 100644 index 0000000..bffdfd9 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.signaller.class.mq5 @@ -0,0 +1,3804 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 1 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + fvgLookupLenght = 5; + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + bool has = false; + int cIdx = barIndex + 1; + int pIdx = cIdx + 1; + ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + cIdx // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + XFIMAConditions fimaConditions; + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Conditions for Finding Signal ... + + // + // TODO: Remove this ... + + // + bool isFastCrossedOverSlow = + fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] && + fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx]; + + // + bool isFastCrossedUnderSlow = + fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] && + fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx]; + + // + has = + isFastCrossedOverSlow || + isFastCrossedUnderSlow; + if (has) + { + // + // Do Conditions Validating ... + // TODO: Igmore All Validations for Testing Purposes ... + + // + // Validate MA Positions ... + double iFastMa = fimaConditions.maFastBuffer[cIdx]; + double iSlowMa = fimaConditions.maSlowBuffer[cIdx]; + double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx]; + double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx]; + + // + // Checking Has FVG ... + XBoxZone fvg; + ENUM_X_DIRECTION fvgDir; + bool hasFVG = patternDetector.HasFVG( + bar, + fvgDir, + fvg, + fvgLookupLenght // + ); + + // + // Checking Crossed On Shadow ... + + // + bool isCrossedOverHappensOnShadow = + isFastCrossedOverSlow && + iFastMa <= bar.GetDown() && + iFastMa >= bar.low; + + // + bool isCrossedUnderHappensOnShadow = + isFastCrossedUnderSlow && + iFastMa <= bar.high && + iFastMa >= bar.GetUp(); + + // + // Bullish Validation ... + bool isBullish = + // + // Has Cross ... + isFastCrossedOverSlow + // + // && + // // + // // Cross Places Based on Fibo ... + // MathMax(iFastMa, iSlowMa) < iFiboLower + // // + // && + // // + // ( + // // + // // Checking FVG ... + // (hasFVG && + // fvg.IsBullish()) + // // + // || + // // + // // Checking Crossed Place ... + // isCrossedOverHappensOnShadow + // // + // ) + // // + ; + + // + // Bearish Validation ... + bool isBearish = + // + // Has Cross ... + isFastCrossedUnderSlow + // + // && + // // + // // Cross Places Based on Fibo ... + // MathMin(iFastMa, iSlowMa) > iFiboUpper + // // + // && + // // + // ( + // // + // // Checking FVG ... + // (hasFVG && + // fvg.IsBearish()) + // // + // || + // // + // // Checking Crossed Place ... + // isCrossedUnderHappensOnShadow + // // + // ) + // // + ; + + // + has = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (has) + { + // + signalDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + + // + // Check Signal Founded ... + has = HasDirection(signalDir); + if (has) + { + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + signalDir, + targets // + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + signal.Clean(); + fimaConditions.Clean(); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Lookup FVG ... + bool LookupFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvgBox // + ) + { + // + bool result = false; + + // + return result; + } + + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + XFIMAPatternDetectorConfig analyserConfig; + + // + // Constructor ... + XCXFIMAStrategy2Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA2", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure Detector ... + analyserConfig.Default(); + analyserConfig.FullDetect(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy2Signaller() + { + // + Destroy(); + + // + analyserConfig.Clean(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void ProcessNewBarNKP(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + XBoxZone iZone; + int count = 0; + bool has = false; + int cIdx = barIndex + 1; + int pIdx = cIdx + 1; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + cIdx // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + + // + // Select Pattern Direction and Price and Price Type ... + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + iPrice = bar.GetPrice(iPriceType); + + // + has = HasDirection(iDir); + } + + // + // Chekc Bullish or Bearish Starter Conditions Exists ... + has = + isBullish || + isBearish; + if (has) + { + // + // Do Conditions Validating ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaHelper.GetMABandUpper(barIndex); + double iMABandLower = fimaHelper.GetMABandLower(barIndex); + + // + // Validate ... + has = isBullish + ? iPrice < iMABandLower + : iPrice > iMABandUpper; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + // has = poiDrawer.DrawBox( + // supportBox, + // iSupportObj, + // true, // Ignore At ... + // supportBox.type // Name ... + // ); + // if (has) + // { + // // + // XPOIStyle iStyle; + // poiDrawer.GetBoxStyle( + // iStyle, + // supportBox.dir // + // ); + // poiDrawer.ApplyBoxStyle( + // iSupportObj, + // iStyle // + // ); + // iStyle.Clean(); + // } + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + // has = poiDrawer.DrawBox( + // resistanceBox, + // iResistanceObj, + // true, // Ignore At ... + // resistanceBox.type // Name ... + // ); + // if (has) + // { + // // + // XPOIStyle iStyle; + // poiDrawer.GetBoxStyle( + // iStyle, + // resistanceBox.dir // + // ); + // poiDrawer.ApplyBoxStyle( + // iResistanceObj, + // iStyle // + // ); + // iStyle.Clean(); + // } + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + + // // + // XCBoxObject *iObj; + // has = fima2Signaller.poiDrawer.DrawBox( + // structure.support, + // iObj); + // if (has) + // { + // } + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + + // // + // XCBoxObject *iObj; + // has = fima2Signaller.poiDrawer.DrawBox( + // structure.resistance, + // iObj); + // if (has) + // { + // } + } + + // + // Validate Positions Support and Resistance Zone ... + int insideZoneIDX = -1; + has = has && + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + + // + // Validate Selected Inside Zone ... + // whith Bars Edge ... + has = IsValidIndex(insideZoneIDX); + if (has) + { + // + if (isBullish) + { + iZone = supports[insideZoneIDX]; + } + else + { + iZone = resistances[insideZoneIDX]; + } + + // + has = isBullish + ? bar.high > supports[insideZoneIDX].upper + : bar.low < resistances[insideZoneIDX].lower; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + else + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + + // + // Checking Liquidities ... + + // + // Do all Draws Here ... + bool canDraw = false; + if (canDraw) + { + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } + } + + // + // Check Signal Founded ... + has = HasDirection(iDir); + if (has) + { + // + // TODO: Provided SL ... + double _point = GetPoints(bar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iZone.Clean(); + signal.Clean(); + structure.Clean(); + fimaConditions.Clean(); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void ProcessNewBarNKP1(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + XBoxZone iZone; + int count = 0; + bool has = false; + int cIdx = 0; + int pIdx = cIdx + 1; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + } + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate Calculations ... + has = HasDirection(iDir) && + (isBullish || + isBearish) && + NotEmptyZero(iPrice) && + NotEmptyZero(iPriceEdge) && + iPrice != iPriceEdge; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Check Petterns Happens ... + // Chekc Bullish or Bearish Starter Conditions Exists ... + has = HasDirection(iDir); + if (has) + { + // + // Do Conditions Validating ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx]; + double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx]; + + // + // Validate ... + + // + // Validate by Edge Price ... + has = isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper; + + // + // Validate by Body Price ... + // has = isBullish + // ? iPrice < iMABandLower + // : iPrice > iMABandUpper; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Validate ... + // Detect Support and Resistances ... + // and Validate Price based on it's ... + has = HasDirection(iDir); + if (has) + { + // + // Validate Positions Support and Resistance Zone ... + int insideZoneIDX = -1; + has = has && + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + + // + // Validate Selected Inside Zone ... + // whith Bars Edge ... + has = IsValidIndex(insideZoneIDX); + if (has) + { + // + if (isBullish) + { + iZone = supports[insideZoneIDX]; + } + else + { + iZone = resistances[insideZoneIDX]; + } + + // + has = isBullish + ? bar.high > supports[insideZoneIDX].upper + : bar.low < resistances[insideZoneIDX].lower; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + else + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Checking Liquidities ... + + // + // Do all Draws Here ... + bool canDraw = true; + if (canDraw) + { + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } + } + + // + // Check Signal Founded ... + has = HasDirection(iDir); + + // + if (has) + { + Print("a Valid ", ToXString(iDir), " Pattern Exists ..."); + } + + // + if (has) + { + // + // TODO: Provided SL ... + double _point = GetPoints(bar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iZone.Clean(); + signal.Clean(); + structure.Clean(); + fimaConditions.Clean(); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + XBoxZone iZone; + int count = 0; + bool has = false; + int cIdx = 0; + int pIdx = cIdx + 1; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + } + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate Calculations ... + has = HasDirection(iDir) && + (isBullish || + isBearish) && + NotEmptyZero(iPrice) && + NotEmptyZero(iPriceEdge) && + iPrice != iPriceEdge; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Strategy 1 ... + has = Strategy1HasSignal( + bar, + iZone, + iName, + supports, + resistances, + iDir, + fimaConditions, + structure // + ); + + // + // Do all Draws Here ... + bool canDraw = true; + if (canDraw && has) + { + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } + } + + // + if (has) + { + Print("a Valid ", ToXString(iDir), " Pattern Exists ..."); + } + + // + if (has) + { + // + // TODO: Provided SL ... + double _point = GetPoints(bar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iZone.Clean(); + signal.Clean(); + structure.Clean(); + fimaConditions.Clean(); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Validate a Pattern based on MA Band ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param patternName: string, detected pattern's name ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool ValidatePatternBasedOnMABand( + XOHCL &bar, + string patternName, + ENUM_X_DIRECTION patternDir, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir) && + fimaConditions.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + // Calculating Price and Price Types ... + + // + isBullish = IsXBullish(patternDir); + isBearish = IsXBearish(patternDir); + + // + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + + // + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate ... + result = + NotEmptyZero(iPrice) && + IsXValid(iPriceType) && + NotEmptyZero(iPriceEdge) && + IsXValid(iPriceEdgeType) && + ((isBullish && !isBearish) || + (isBearish && !isBullish)); + if (!result) + { + return result; + } + + // + // Validate Pattern based on MA Band ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx]; + double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx]; + + // + // Validate by Edge Price ... + result = isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions, + XFIMAMarketStructure &fimaMarketStructure // + ) + { + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir) && + fimaConditions.IsValid(); + if (!result) + { + return result; + } + + // + // Validate Pattern Based on MA Band ... + result = ValidatePatternBasedOnMABand( + bar, + patternName, + patternDir, + fimaConditions // + ); + if (!result) + { + return result; + } + + // + // Check Affected Zone ... + // Select a Support or Resistance ... + int insideZoneIDX = -1; + result = + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + if (!result) + { + return result; + } + + // + // Filling Affected Zone ... + // and Validate it ... + if (IsXBullish(patternDir)) + { + iZone = supports[insideZoneIDX]; + } + else if (IsXBearish(patternDir)) + { + iZone = resistances[insideZoneIDX]; + } + result = iZOne.IsValid(); + if (!result) + { + return result; + } + + // + // Validate affected Zone based on Pattern's Bar ... + result = IsXBullish(patternDir) + ? bar.high > iZZone.upper + : IsXBearish(patternDir) + ? bar.low < iZone.lower + : false; + // + // Cleanup Resources ... + if (!result) + { + iZone.Clean(); + } + + // + return result; + } + + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions, + XFIMAMarketStructure &fimaMarketStructure // + ) + { + // + bool result = false; + + // + // Prepare ... + + // + // Validate ... + + // + // Do Detection ... + + // + // Validate result ... + + // + // Cleanup Resources ... + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.detector.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.detector.class.mq5 new file mode 100644 index 0000000..ac1fcbd --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -0,0 +1,495 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAPoiDetector ... +// Description: XFIMA POI Detector 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 XFIMA POI Detector Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.xfima.lib.mq5" + +// +// Implementation ... +class XCXFIMAPOIDetector : public XCMarketPatternDetector +{ + // + // Public ... + public: + // + // Props ... + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCXFIMAHelper *fimaHelper; // XFIMA Helper ... + + // + // Constructor ... + XCXFIMAPOIDetector( + XCXFIMAHelper *_fimaHelper // + ) : XCMarketPatternDetector() + { + // + barAnalyser = new XCBarAnalyser(); + fimaHelper = _fimaHelper; + } + + // + // Deconstructor ... + ~XCXFIMAPOIDetector() + { + Destroy(); + } + + // + // Actions and Tools ... + + // + // Pivot Analysors ... + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ + bool AnalysePVPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractPVPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XPV", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ + bool AnalyseMAPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractMAPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XMA", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ + bool AnalyseSARPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractSARPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XSAR", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ + bool AnalyseZigZagPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractZigZagPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XZG", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Destroy ... + */ + void Destroy() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Testers ... + + /** + * Analyse Market based on Specified Bar ... + * + * @param structure: XFIMAMarketStructure, reference to holds result ... + * @param config: XFIMAMarketStructureConfig, reference to Configure Detector ... + * @param barIndex: int, Bar Index ... + */ + void AnalyseMarket( + XFIMAMarketStructure &structure, + XFIMAMarketStructureConfig &config, + int barIndex = 0 // + ) + { + // + // Prepare ... + structure.Clean(); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = false; + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + has = structure.bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + structure.Clean(); + return; + } + + // + // Reading Bar Patterns ... + XOHCL iBar; + XPatternAnalysis iPatternAnalysis; + for (int i = barIndex; i < barIndex + config.loopback; i++) + { + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); + + // + // Initialize Indexed Bar ... + // + has = structure.bar.BarAt(i, iBar); + if (!has) + { + break; + } + + // + // Analyse Indexed Bar ... + has = AnalyseBarPatterns(iBar, iPatternAnalysis, config.barsAnalysisConfig); + if (has) + { + // + AddRef( + iPatternAnalysis, + structure.barsAnalysis // + ); + + // + if (i == barIndex) + { + structure.barAnalysis = iPatternAnalysis; + } + } + + // + // Check Satisfied ... + has = ArraySize(structure.barsAnalysis) >= config.requiredPivots; + if (has) + { + break; + } + } + + // + // Handle Pivot Analysis ... + + // + // XPV ... + if (config.analysePVPivots) + { + // + // Reading Pivots ... + has = AnalysePVPivots( + structure.pvAnalysis, + barIndex, + config.requiredPivots, + config.loopback, + config.pvPivotsValidationLength // + ); + if (!has) + { + structure.pvAnalysis.Clean(); + } + } + + // + // XZG ... + if (config.analyseZGPivots) + { + // + // Reading Pivots ... + has = AnalyseZigZagPivots( + structure.zgAnalysis, + barIndex, + config.requiredPivots, + config.loopback // + ); + if (!has) + { + structure.zgAnalysis.Clean(); + } + } + + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.drawer.class copy.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.drawer.class copy.mq5 new file mode 100644 index 0000000..808c889 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.drawer.class copy.mq5 @@ -0,0 +1,1775 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAPoiDrawer ... +// Description: XFIMA 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 XFIMA POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.xfima.lib.mq5" + +// +// Implementation ... +class XCXFIMAPOIDrawer : public XCPOIDrawer +{ + // + public: + // + // Props ... + + // + // Tested Zones ... + color testedBullishColor; + color testedBearishColor; + + // + // Breaked Zones ... + color breakedBullishColor; + color breakedBearishColor; + + // + // FakeBreaked Zones ... + color fakeBreakedBullishColor; + color fakeBreakedBearishColor; + + // + // Constructor ... + XCXFIMAPOIDrawer() : XCPOIDrawer() + { + Default(); + } + + // + // Deconstructor ... + ~XCXFIMAPOIDrawer() + { + } + + // + // Overrides ... + + /** + * Do additional Configurations for Child Classes ... + */ + void virtual Default() override + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrAqua; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrMagenta; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + + // + testedBullishColor = clrLime; + breakedBullishColor = clrGreen; + fakeBreakedBullishColor = clrYellow; + + // + testedBearishColor = clrRed; + breakedBearishColor = clrDarkRed; + fakeBreakedBearishColor = clrDarkOrange; + } + + // + // Get Specified Directional Arrow Anchor ... + ENUM_ARROW_ANCHOR GetArrowAnchor(ENUM_X_DIRECTION forDir) + { + // + ENUM_ARROW_ANCHOR result = ANCHOR_BOTTOM; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + int GetArrowCode(ENUM_X_DIRECTION forDir) + { + // + int result = 159; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? 233 + : 234; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + color GetArrowColor(ENUM_X_DIRECTION forDir) + { + // + color result = clrYellow; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? clrAqua + : clrMagenta; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Price Type ... + ENUM_X_PRICE GetArrowPriceType(ENUM_X_DIRECTION forDir) + { + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? X_PRICE_LOW + : X_PRICE_HIGH; + } + + // + return result; + } + + /** + * Get Tested Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetTestedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? testedBullishColor + : testedBearishColor; + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetPatternStyle( + style, + zone.dir // + ); + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param forDir: Specified Direction ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + forDir // + ); + + // + style.width = 2; + style.style = STYLE_DASH; + + // + return result; + } + + /** + * Get Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? breakedBullishColor + : breakedBearishColor; + + // + return result; + } + + /** + * Get Fake Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetFakeBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? fakeBreakedBullishColor + : fakeBreakedBearishColor; + + // + return result; + } + + /** + * Fill Arrow Based Drawing Specs ... + * + * @param forDir: Specified Direction ... + * @param arrowPriceType: ENUM_X_PRICE, refrence for Arrow Price ... + * @param arrowCode: int, reference for Arrow Code ... + * @param arrowWidth: int, reference for Arrow Width ... + * @param arrowColor: color, reference for Arrow Color ... + * @param arrowAnchor: ENUM_ARROW_ANCHOR, reference for Arrow Anchor ... + */ + void FillArrowSpecs( + ENUM_X_DIRECTION forDir, + ENUM_X_PRICE &arrowPriceType, + int &arrowCode, + int &arrowWidth, + color &arrowColor, + ENUM_ARROW_ANCHOR &arrowAnchor // + ) + { + // + // Prepare ... + arrowCode = 159; + arrowWidth = 2; + arrowColor = CLR_NONE; + arrowAnchor = ANCHOR_BOTTOM; + arrowPriceType = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + arrowCode = GetArrowCode(forDir); + arrowColor = GetArrowColor(forDir); + arrowAnchor = GetArrowAnchor(forDir); + arrowPriceType = GetArrowPriceType(forDir); + } + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyTestedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetTestedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Breaked Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyBreakedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyFakeBreakStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetFakeBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Pattern Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPatternStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetPatternStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPatternsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBoxObject *iBoxObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iBoxObj = (XCBoxObject *)objects.At(i); + iName = iBoxObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + /** + * Apply Style to Specified Pivot Object ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPivotStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPivotsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBarArrowObject *iObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iObj = (XCBarArrowObject *)objects.At(i); + iName = iObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyPivotStyle( + iObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iObj); + } + } + + /** + * Draw Specified Market Structure Based on Given Configs ... + * + * @param structure: XFIMAMarketStructure, reference to Provide Specifid Market Structure ... + * @param config: XFIMAMarketStructureDrawerConfig, reference to Provide Drawing Configurations ... + * @param objects: CArrayObj, pointer reference to Holds drawn Objects instances ... + * + * @return ( int ) + */ + int DrawMarketStructure( + XFIMAMarketStructure &structure, + XFIMAMarketStructureDrawerConfig &config, + CArrayObj *&objects // + ) + { + // + int result = 0; + + // + // Normalize ... + if (objects == NULL) + { + objects = new CArrayObj(); + } + + // + // Prepare ... + // objects.Clear(); + + // + int count = 0; + bool has = false; + int arrowCode = -1; + int arrowWidth = 3; + string arrowName = NULL; + color arrowColor = CLR_NONE; + ENUM_X_PRICE arrowPriceType = X_PRICE_CLOSE; + ENUM_ARROW_ANCHOR arrowAnchor = ANCHOR_BOTTOM; + + // + int bullArrowCode = GetArrowCode(X_DIRECTION_BULLISH); + int bearArrowCode = GetArrowCode(X_DIRECTION_BEARISH); + + // + // Validate ... + has = structure.bar.IsValid(); + if (!has) + { + return result; + } + + // + // Apply Drawing Methods ... + + // // + // // OB ... + // if (config.drawOB) + // { + // // + // // Validate ... + // has = structure.ob.IsValid(); + // if (has) + // { + // // + // XCBoxObject *iObj; + // has = DrawBox( + // structure.ob, + // iObj // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // FVG ... + // if (config.drawFVG) + // { + // // + // // Validate ... + // has = structure.fvg.IsValid(); + // if (has) + // { + // // + // XCBoxObject *iObj; + // has = DrawBox( + // structure.fvg, + // iObj // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // Support ... + // if (config.drawSupport) + // { + // // + // // Validate ... + // has = structure.support.IsValid(); + // if (has) + // { + // // + // XCBoxObject *iObj; + // has = DrawBox( + // structure.support, + // iObj // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // Resistance ... + // if (config.drawResistance) + // { + // // + // // Validate ... + // has = structure.resistance.IsValid(); + // if (has) + // { + // // + // XCBoxObject *iObj; + // has = DrawBox( + // structure.resistance, + // iObj // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // Swing Trend ... + // if (config.drawSwingTrend) + // { + // // + // // Validate ... + // has = HasDirection(structure.trendDir) && + // HasChild(structure.trendSwings); + // if (has) + // { + // // + // CChartObjectTrend *iObj; + // has = DrawSwingTrend( + // structure.trendSwings, + // structure.trendDir, + // iObj, // + // config.swingTrendRayRight, // Ray Right ... + // config.swingTrendRayLeft // Ray Left ... + // ); + // if (has) + // { + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // Start Pattern ... + // if (config.drawStarPattern) + // { + // // + // // Validate ... + // has = HasDirection(structure.starPatternDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.starPatternDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XStar_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Flag Pattern ... + // if (config.drawFlagPattern) + // { + // // + // // Validate ... + // has = HasDirection(structure.flagPatternDir) && + // structure.flagSwing.IsValid(); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.flagPatternDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XFlag_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Rising Pattern ... + // if (config.drawRisingPattern) + // { + // // + // // Validate ... + // has = HasDirection(structure.risingPatternDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.risingPatternDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XRise_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Piercing Pattern ... + // if (config.drawPiercingPattern) + // { + // // + // // Validate ... + // has = HasDirection(structure.piercingPatternDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.piercingPatternDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XPiercing_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Signal Key Bar Pattern ... + // if (config.drawSignalKeyBarPattern) + // { + // // + // // Validate ... + // has = HasDirection(structure.signalKeyBarPatternDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.signalKeyBarPatternDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XSignalKey_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Pinned Bar ... + // if (config.drawPinned) + // { + // // + // // Validate ... + // has = HasDirection(structure.pinnedDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.pinnedDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XPin_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Momentum Bar ... + // if (config.drawMomentum) + // { + // // + // // Validate ... + // has = HasDirection(structure.momentumDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.momentumDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XMomentum_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Engulfed Bar ... + // if (config.drawEngulfed) + // { + // // + // // Validate ... + // has = HasDirection(structure.engulfedDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.engulfedDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XEngulf_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // True Gaped Bar ... + // if (config.drawTrueGaped) + // { + // // + // // Validate ... + // has = HasDirection(structure.trueGapedDir); + // if (has) + // { + // // + // FillArrowSpecs( + // structure.trueGapedDir, + // arrowPriceType, + // arrowCode, + // arrowWidth, + // arrowColor, + // arrowAnchor // + // ); + // XCBarArrowObject *iObj; + // arrowName = "XTrueGap_" + ToMD5(structure.bar.time); + // has = DrawBarArrow( + // structure.bar, + // iObj, + // arrowPriceType, + // arrowCode, + // arrowColor, + // arrowWidth, + // arrowAnchor, + // arrowName // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // XFIMA PV Analysis ... + // if (config.drawFIMAPVPivotsAnalysis) + // { + // // + // // Validate ... + // has = structure.pvAnalysis.IsValid(); + // if (has) + // { + // // + // XCPivotAnalysisObject *iObj; + // has = DrawPivotAnalysis( + // structure.pvAnalysis, + // iObj, + // config.drawFIMAPVPivotsAnalysisTrends, + // config.drawFIMAPVPivotsAnalysisZones, + // config.drawFIMAPVPivotsAnalysisPivots, + // bearArrowCode, + // bullArrowCode // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // XFIMA Sar Analysis ... + // if (config.drawFIMASARPivotsAnalysis) + // { + // // + // // Validate ... + // has = structure.sarAnalysis.IsValid(); + // if (has) + // { + // // + // XCPivotAnalysisObject *iObj; + // has = DrawPivotAnalysis( + // structure.pvAnalysis, + // iObj, + // config.drawFIMASARPivotsAnalysisTrends, + // config.drawFIMASARPivotsAnalysisZones, + // config.drawFIMASARPivotsAnalysisPivots, + // bearArrowCode, + // bullArrowCode // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // XFIMA ZigZag Analysis ... + // if (config.drawFIMAZigZagPivotsAnalysis) + // { + // // + // // Validate ... + // has = structure.zigzagAnalysis.IsValid(); + // if (has) + // { + // // + // XCPivotAnalysisObject *iObj; + // has = DrawPivotAnalysis( + // structure.pvAnalysis, + // iObj, + // config.drawFIMAZigZagPivotsAnalysisTrends, + // config.drawFIMAZigZagPivotsAnalysisZones, + // config.drawFIMAZigZagPivotsAnalysisPivots, + // bearArrowCode, + // bullArrowCode // + // ); + // if (has) + // { + // objects.Add(iObj); + // } + // } + // } + + // // + // // Fake Breaked Zone ... + // if (config.drawFakeBreakedZone && + // structure.fakeBreakedZone.IsValid()) + // { + // // + // XCBoxObject *iObj; + // has = DrawBox( + // structure.fakeBreakedZone, + // iObj // + // ); + // if (has) + // { + // // + // // Apply Style ... + // ApplyFakeBreakStyle( + // iObj, + // structure.fakeBreakedZone // + // ); + + // // + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + + // // + // // Recently Tested Zones ... + // if (config.drawRecentlyTestedZones && + // HasChild(structure.recentlyTestedZones)) + // { + // // + // XCBoxObject *iObj; + // count = ArraySize(structure.recentlyTestedZones); + // for (int i = 0; i < count; i++) + // { + // // + // // Draw Box ... + // has = DrawBox( + // structure.recentlyTestedZones[i], + // iObj // + // ); + // if (has) + // { + // // + // ApplyTestedStyle( + // iObj, + // structure.recentlyTestedZones[i] // + // ); + + // // + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // Recently Breaked Zones ... + // if (config.drawRecentlyBreakedZones && + // HasChild(structure.recentlyBreakedZones)) + // { + // // + // XCBoxObject *iObj; + // count = ArraySize(structure.recentlyBreakedZones); + // for (int i = 0; i < count; i++) + // { + // // + // // Draw Box ... + // has = DrawBox( + // structure.recentlyBreakedZones[i], + // iObj // + // ); + // if (has) + // { + // // + // ApplyBreakedStyle( + // iObj, + // structure.recentlyBreakedZones[i] // + // ); + + // // + // objects.Add(iObj); + // } + + // // + // ZeroMemory(iObj); + // } + // } + + // // + // // Draw Recent Patterns ... + // if (config.drawRecentPatterns) + // { + // // + // int baseArrowCode = 159; + // CArrayObj *patternObjects; + + // // + // // Order Blocs ... + // if (config.drawOB && + // HasChild(structure.obs)) + // { + // // + // count = DrawBoxes( + // structure.obs, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Fair Value Gaps ... + // if (config.drawFVG && + // HasChild(structure.fvgs)) + // { + // // + // count = DrawBoxes( + // structure.fvgs, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Supports ... + // if (config.drawSupport && + // HasChild(structure.supports)) + // { + // // + // count = DrawBoxes( + // structure.supports, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Resistances ... + // if (config.drawResistance && + // HasChild(structure.obs)) + // { + // // + // count = DrawBoxes( + // structure.resistances, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Pin Bars ... + // if (config.drawPinned && + // HasChild(structure.pinBars)) + // { + // // + // count = DrawPivots( + // structure.pinBars, + // patternObjects, + // baseArrowCode, + // baseArrowCode // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPivotsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Engulf Bars ... + // if (config.drawEngulfed && + // HasChild(structure.engulfBars)) + // { + // // + // count = DrawPivots( + // structure.engulfBars, + // patternObjects, + // baseArrowCode, + // baseArrowCode // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPivotsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // TrueGap Bars ... + // if (config.drawTrueGaped && + // HasChild(structure.trueGapBars)) + // { + // // + // count = DrawPivots( + // structure.trueGapBars, + // patternObjects, + // baseArrowCode, + // baseArrowCode // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPivotsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Momentum Bars ... + // if (config.drawMomentum && + // HasChild(structure.momentumBars)) + // { + // // + // count = DrawPivots( + // structure.momentumBars, + // patternObjects, + // baseArrowCode, + // baseArrowCode // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPivotsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Flag Pattern ... + // if (config.drawFlagPattern && + // HasChild(structure.flagPatterns)) + // { + // // + // count = DrawBoxes( + // structure.flagPatterns, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Star Pattern ... + // if (config.drawStarPattern && + // HasChild(structure.starPatterns)) + // { + // // + // count = DrawBoxes( + // structure.starPatterns, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Rising Pattern ... + // if (config.drawRisingPattern && + // HasChild(structure.risingPatterns)) + // { + // // + // count = DrawBoxes( + // structure.risingPatterns, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // Piercing Pattern ... + // if (config.drawPiercingPattern && + // HasChild(structure.piercingPatterns)) + // { + // // + // count = DrawBoxes( + // structure.piercingPatterns, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + + // // + // // SignalKeyBar Pattern ... + // if (config.drawSignalKeyBarPattern && + // HasChild(structure.signalKeyBarPatterns)) + // { + // // + // count = DrawBoxes( + // structure.signalKeyBarPatterns, + // patternObjects // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // ApplyPatternsStyle(patternObjects); + + // // + // AddObjects( + // patternObjects, + // objects // + // ); + // } + + // // + // ZeroMemory(patternObjects); + // } + // } + + // + result = objects.Total(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.drawer.class.mq5 b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..8e2661c --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-saherelm.xfima.x-poi.drawer.class.mq5 @@ -0,0 +1,1949 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAPoiDrawer ... +// Description: XFIMA 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 XFIMA POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.xfima.lib.mq5" + +// +// Implementation ... +class XCXFIMAPOIDrawer : public XCPOIDrawer +{ + // + public: + // + // Props ... + + // + // Tested Zones ... + color testedBullishColor; + color testedBearishColor; + + // + // Breaked Zones ... + color breakedBullishColor; + color breakedBearishColor; + + // + // FakeBreaked Zones ... + color fakeBreakedBullishColor; + color fakeBreakedBearishColor; + + // + // Constructor ... + XCXFIMAPOIDrawer() : XCPOIDrawer() + { + Default(); + } + + // + // Deconstructor ... + ~XCXFIMAPOIDrawer() + { + } + + // + // Overrides ... + + /** + * Do additional Configurations for Child Classes ... + */ + void virtual Default() override + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrAqua; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrMagenta; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + + // + testedBullishColor = clrLime; + breakedBullishColor = clrGreen; + fakeBreakedBullishColor = clrYellow; + + // + testedBearishColor = clrRed; + breakedBearishColor = clrDarkRed; + fakeBreakedBearishColor = clrDarkOrange; + } + + // + // Get Specified Directional Arrow Anchor ... + ENUM_ARROW_ANCHOR GetArrowAnchor(ENUM_X_DIRECTION forDir) + { + // + ENUM_ARROW_ANCHOR result = ANCHOR_BOTTOM; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + int GetArrowCode(ENUM_X_DIRECTION forDir) + { + // + int result = 159; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? 233 + : 234; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + color GetArrowColor(ENUM_X_DIRECTION forDir) + { + // + color result = clrYellow; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? clrAqua + : clrMagenta; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Price Type ... + ENUM_X_PRICE GetArrowPriceType(ENUM_X_DIRECTION forDir) + { + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? X_PRICE_LOW + : X_PRICE_HIGH; + } + + // + return result; + } + + /** + * Get Tested Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetTestedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? testedBullishColor + : testedBearishColor; + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetPatternStyle( + style, + zone.dir // + ); + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param forDir: Specified Direction ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + forDir // + ); + + // + style.width = 2; + style.style = STYLE_DASH; + + // + return result; + } + + /** + * Get Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? breakedBullishColor + : breakedBearishColor; + + // + return result; + } + + /** + * Get Fake Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetFakeBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? fakeBreakedBullishColor + : fakeBreakedBearishColor; + + // + return result; + } + + /** + * Fill Arrow Based Drawing Specs ... + * + * @param forDir: Specified Direction ... + * @param arrowPriceType: ENUM_X_PRICE, refrence for Arrow Price ... + * @param arrowCode: int, reference for Arrow Code ... + * @param arrowWidth: int, reference for Arrow Width ... + * @param arrowColor: color, reference for Arrow Color ... + * @param arrowAnchor: ENUM_ARROW_ANCHOR, reference for Arrow Anchor ... + */ + void FillArrowSpecs( + ENUM_X_DIRECTION forDir, + ENUM_X_PRICE &arrowPriceType, + int &arrowCode, + int &arrowWidth, + color &arrowColor, + ENUM_ARROW_ANCHOR &arrowAnchor // + ) + { + // + // Prepare ... + arrowCode = 159; + arrowWidth = 2; + arrowColor = CLR_NONE; + arrowAnchor = ANCHOR_BOTTOM; + arrowPriceType = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + arrowCode = GetArrowCode(forDir); + arrowColor = GetArrowColor(forDir); + arrowAnchor = GetArrowAnchor(forDir); + arrowPriceType = GetArrowPriceType(forDir); + } + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyTestedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetTestedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Breaked Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyBreakedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyFakeBreakStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetFakeBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Pattern Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPatternStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetPatternStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPatternsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBoxObject *iBoxObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iBoxObj = (XCBoxObject *)objects.At(i); + iName = iBoxObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + /** + * Apply Style to Specified Pivot Object ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPivotStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPivotsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBarArrowObject *iObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iObj = (XCBarArrowObject *)objects.At(i); + iName = iObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyPivotStyle( + iObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iObj); + } + } + + /** + * Draw Specified Market Structure Based on Given Configs ... + * + * @param structure: XFIMAMarketStructure, reference to Provide Specifid Market Structure ... + * @param config: XFIMAMarketStructureDrawerConfig, reference to Provide Drawing Configurations ... + * @param objects: CArrayObj, pointer reference to Holds drawn Objects instances ... + * + * @return ( int ) + */ + int DrawMarketStructure( + XFIMAMarketStructure &structure, + XFIMAMarketStructureDrawerConfig &config, + CArrayObj *&objects // + ) + { + // + int result = 0; + + // + // Normalize ... + if (objects == NULL) + { + objects = new CArrayObj(); + } + + // + // Prepare ... + // objects.Clear(); + + // + int count = 0; + bool has = false; + int arrowCode = -1; + int arrowWidth = 3; + string arrowName = NULL; + color arrowColor = CLR_NONE; + ENUM_X_PRICE arrowPriceType = X_PRICE_CLOSE; + ENUM_ARROW_ANCHOR arrowAnchor = ANCHOR_BOTTOM; + + // + int bullArrowCode = GetArrowCode(X_DIRECTION_BULLISH); + int bearArrowCode = GetArrowCode(X_DIRECTION_BEARISH); + + // + // Validate ... + has = structure.bar.IsValid(); + if (!has) + { + return result; + } + + // + // Apply Drawing Methods ... + + // + // OB ... + if (config.drawOB) + { + // + // Validate ... + has = structure.ob.IsValid(); + if (has) + { + // + XCBoxObject *iObj; + has = DrawBox( + structure.ob, + iObj // + ); + if (has) + { + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // FVG ... + if (config.drawFVG) + { + // + // Validate ... + has = structure.fvg.IsValid(); + if (has) + { + // + XCBoxObject *iObj; + has = DrawBox( + structure.fvg, + iObj // + ); + if (has) + { + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // Support ... + if (config.drawSupport) + { + // + // Validate ... + has = structure.support.IsValid(); + if (has) + { + // + XCBoxObject *iObj; + has = DrawBox( + structure.support, + iObj // + ); + if (has) + { + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // Resistance ... + if (config.drawResistance) + { + // + // Validate ... + has = structure.resistance.IsValid(); + if (has) + { + // + XCBoxObject *iObj; + has = DrawBox( + structure.resistance, + iObj // + ); + if (has) + { + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // Swing Trend ... + if (config.drawSwingTrend) + { + // + // Validate ... + has = HasDirection(structure.trendDir) && + HasChild(structure.trendSwings); + if (has) + { + // + CChartObjectTrend *iObj; + has = DrawSwingTrend( + structure.trendSwings, + structure.trendDir, + iObj, // + config.swingTrendRayRight, // Ray Right ... + config.swingTrendRayLeft // Ray Left ... + ); + if (has) + { + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // Start Pattern ... + if (config.drawStarPattern) + { + // + // Validate ... + has = HasDirection(structure.starPatternDir); + if (has) + { + // + FillArrowSpecs( + structure.starPatternDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XStar_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Flag Pattern ... + if (config.drawFlagPattern) + { + // + // Validate ... + has = HasDirection(structure.flagPatternDir) && + structure.flagSwing.IsValid(); + if (has) + { + // + FillArrowSpecs( + structure.flagPatternDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XFlag_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Rising Pattern ... + if (config.drawRisingPattern) + { + // + // Validate ... + has = HasDirection(structure.risingPatternDir); + if (has) + { + // + FillArrowSpecs( + structure.risingPatternDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XRise_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Piercing Pattern ... + if (config.drawPiercingPattern) + { + // + // Validate ... + has = HasDirection(structure.piercingPatternDir); + if (has) + { + // + FillArrowSpecs( + structure.piercingPatternDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XPiercing_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Signal Key Bar Pattern ... + if (config.drawSignalKeyBarPattern) + { + // + // Validate ... + has = HasDirection(structure.signalKeyBarPatternDir); + if (has) + { + // + FillArrowSpecs( + structure.signalKeyBarPatternDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XSignalKey_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Pinned Bar ... + if (config.drawPinned) + { + // + // Validate ... + has = HasDirection(structure.pinnedDir); + if (has) + { + // + FillArrowSpecs( + structure.pinnedDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XPin_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Momentum Bar ... + if (config.drawMomentum) + { + // + // Validate ... + has = HasDirection(structure.momentumDir); + if (has) + { + // + FillArrowSpecs( + structure.momentumDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XMomentum_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Engulfed Bar ... + if (config.drawEngulfed) + { + // + // Validate ... + has = HasDirection(structure.engulfedDir); + if (has) + { + // + FillArrowSpecs( + structure.engulfedDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XEngulf_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // True Gaped Bar ... + if (config.drawTrueGaped) + { + // + // Validate ... + has = HasDirection(structure.trueGapedDir); + if (has) + { + // + FillArrowSpecs( + structure.trueGapedDir, + arrowPriceType, + arrowCode, + arrowWidth, + arrowColor, + arrowAnchor // + ); + XCBarArrowObject *iObj; + arrowName = "XTrueGap_" + ToMD5(structure.bar.time); + has = DrawBarArrow( + structure.bar, + iObj, + arrowPriceType, + arrowCode, + arrowColor, + arrowWidth, + arrowAnchor, + arrowName // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // XFIMA PV Analysis ... + if (config.drawFIMAPVPivotsAnalysis) + { + // + // Validate ... + has = structure.pvAnalysis.IsValid(); + if (has) + { + // + XCPivotAnalysisObject *iObj; + has = DrawPivotAnalysis( + structure.pvAnalysis, + iObj, + config.drawFIMAPVPivotsAnalysisTrends, + config.drawFIMAPVPivotsAnalysisZones, + config.drawFIMAPVPivotsAnalysisPivots, + bearArrowCode, + bullArrowCode // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // XFIMA Sar Analysis ... + if (config.drawFIMASARPivotsAnalysis) + { + // + // Validate ... + has = structure.sarAnalysis.IsValid(); + if (has) + { + // + XCPivotAnalysisObject *iObj; + has = DrawPivotAnalysis( + structure.pvAnalysis, + iObj, + config.drawFIMASARPivotsAnalysisTrends, + config.drawFIMASARPivotsAnalysisZones, + config.drawFIMASARPivotsAnalysisPivots, + bearArrowCode, + bullArrowCode // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // XFIMA ZigZag Analysis ... + if (config.drawFIMAZigZagPivotsAnalysis) + { + // + // Validate ... + has = structure.zigzagAnalysis.IsValid(); + if (has) + { + // + XCPivotAnalysisObject *iObj; + has = DrawPivotAnalysis( + structure.pvAnalysis, + iObj, + config.drawFIMAZigZagPivotsAnalysisTrends, + config.drawFIMAZigZagPivotsAnalysisZones, + config.drawFIMAZigZagPivotsAnalysisPivots, + bearArrowCode, + bullArrowCode // + ); + if (has) + { + objects.Add(iObj); + } + } + } + + // + // Fake Breaked Zone ... + if (config.drawFakeBreakedZone && + structure.fakeBreakedZone.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + structure.fakeBreakedZone, + iObj // + ); + if (has) + { + // + // Apply Style ... + ApplyFakeBreakStyle( + iObj, + structure.fakeBreakedZone // + ); + + // + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Recently Tested Zones ... + if (config.drawRecentlyTestedZones && + HasChild(structure.recentlyTestedZones)) + { + // + XCBoxObject *iObj; + count = ArraySize(structure.recentlyTestedZones); + for (int i = 0; i < count; i++) + { + // + // Draw Box ... + has = DrawBox( + structure.recentlyTestedZones[i], + iObj // + ); + if (has) + { + // + ApplyTestedStyle( + iObj, + structure.recentlyTestedZones[i] // + ); + + // + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // Recently Breaked Zones ... + if (config.drawRecentlyBreakedZones && + HasChild(structure.recentlyBreakedZones)) + { + // + XCBoxObject *iObj; + count = ArraySize(structure.recentlyBreakedZones); + for (int i = 0; i < count; i++) + { + // + // Draw Box ... + has = DrawBox( + structure.recentlyBreakedZones[i], + iObj // + ); + if (has) + { + // + ApplyBreakedStyle( + iObj, + structure.recentlyBreakedZones[i] // + ); + + // + objects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + } + + // + // Draw Recent Patterns ... + if (config.drawRecentPatterns) + { + // + int baseArrowCode = 159; + CArrayObj *patternObjects; + + // + // Order Blocs ... + if (config.drawOB && + HasChild(structure.obs)) + { + // + count = DrawBoxes( + structure.obs, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Fair Value Gaps ... + if (config.drawFVG && + HasChild(structure.fvgs)) + { + // + count = DrawBoxes( + structure.fvgs, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Supports ... + if (config.drawSupport && + HasChild(structure.supports)) + { + // + count = DrawBoxes( + structure.supports, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Resistances ... + if (config.drawResistance && + HasChild(structure.obs)) + { + // + count = DrawBoxes( + structure.resistances, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Pin Bars ... + if (config.drawPinned && + HasChild(structure.pinBars)) + { + // + count = DrawPivots( + structure.pinBars, + patternObjects, + baseArrowCode, + baseArrowCode // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPivotsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Engulf Bars ... + if (config.drawEngulfed && + HasChild(structure.engulfBars)) + { + // + count = DrawPivots( + structure.engulfBars, + patternObjects, + baseArrowCode, + baseArrowCode // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPivotsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // TrueGap Bars ... + if (config.drawTrueGaped && + HasChild(structure.trueGapBars)) + { + // + count = DrawPivots( + structure.trueGapBars, + patternObjects, + baseArrowCode, + baseArrowCode // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPivotsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Momentum Bars ... + if (config.drawMomentum && + HasChild(structure.momentumBars)) + { + // + count = DrawPivots( + structure.momentumBars, + patternObjects, + baseArrowCode, + baseArrowCode // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPivotsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Flag Pattern ... + if (config.drawFlagPattern && + HasChild(structure.flagPatterns)) + { + // + count = DrawBoxes( + structure.flagPatterns, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Star Pattern ... + if (config.drawStarPattern && + HasChild(structure.starPatterns)) + { + // + count = DrawBoxes( + structure.starPatterns, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Rising Pattern ... + if (config.drawRisingPattern && + HasChild(structure.risingPatterns)) + { + // + count = DrawBoxes( + structure.risingPatterns, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // Piercing Pattern ... + if (config.drawPiercingPattern && + HasChild(structure.piercingPatterns)) + { + // + count = DrawBoxes( + structure.piercingPatterns, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + + // + // SignalKeyBar Pattern ... + if (config.drawSignalKeyBarPattern && + HasChild(structure.signalKeyBarPatterns)) + { + // + count = DrawBoxes( + structure.signalKeyBarPatterns, + patternObjects // + ); + has = IsValidSize(count); + if (has) + { + // + ApplyPatternsStyle(patternObjects); + + // + AddObjects( + patternObjects, + objects // + ); + } + + // + ZeroMemory(patternObjects); + } + } + + // + result = objects.Total(); + + // + return result; + } + + // +}; + +/** + * Draw Pivot Analysis ... + * + * @param analysis: XPivotAnalysis, referece Specified Pivot Analysis ... + * @param object: XCPivotAnalysisObject, pointer reference for Drawn Object ... + * @param drawTrends: Specified to Draw Trends or not ... + * @param drawZones: Specified to Draw Support and Resistance Zones or not ... + * @param drawPivots: Specified to Draw Pivots or not ... + * @param peakArrow: int, Specified Arrow Code for Peak Pivots ... + * @param valeArrow: int, Specified Arrow Code for Vale Pivots ... + * @param threshold: int, distance between price and arrow in Point ... + * + * @return ( bool ) + */ +bool DrawPivotAnalysis( + XPivotAnalysis &analysis, + XCPivotAnalysisObject *&object, + bool drawTrends = true, + bool drawZones = true, + bool drawPivots = true, + int peakArrow = 159, + int valeArrow = 159, + int threshold = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + object = NULL; + + // + // Normalize ... + + // + // Validate ... + result = analysis.IsValid() && + analysis.IsAnalysed(); + if (!result) + { + return result; + } + + // + object = new XCPivotAnalysisObject(); + result = object.Create( + ChartIdentification(), + SubWindowIdentification(), + analysis, + drawTrends, + drawZones, + drawPivots, + peakArrow, + valeArrow, + threshold // + ); + if (result) + { + // + ApplyPivotAnalysisStyle( + object, + analysis // + ); + } + + // + return result; +} + +/** + * Apply Specified Style to Specified Object ... + * + * @param object: CChartObject, pointer reference of Object ... + * @param model: XPivotAnalysis, referece to access requirements ... + */ +void ApplyPivotAnalysisStyle( + XCPivotAnalysisObject *&object, + XPivotAnalysis &model // +) +{ + // + // Validate ... + bool has = model.IsValid() && + model.IsAnalysed() && + object != NULL; + if (!has) + { + return; + } + + // + XPOIStyle style; + + // + // Support ... + style = defaultBullishStyle; + object.SupportColor(style.clr); + object.SupportWidth(style.width); + object.SupportStyle(style.style); + + // + // Resistance ... + style = defaultBearishStyle; + object.ResistanceColor(style.clr); + object.ResistanceWidth(style.width); + object.ResistanceStyle(style.style); + + // + // Upper ... + if (model.IsPeakAnalysed()) + { + // + GetStyle( + style, + model.peakDir // + ); + if (!HasDirection(model.peakDir)) + { + // + style.Default(); + style.clr = clrGray; + } + + // + object.UpperColor(style.clr); + object.UpperWidth(style.width); + object.UpperStyle(style.style); + object.UpperRayLeft(false); + object.UpperRayRight(true); + } + + // + // Lower ... + if (model.IsValeAnalysed()) + { + // + GetStyle( + style, + model.valeDir // + ); + if (!HasDirection(model.valeDir)) + { + // + style.Default(); + style.clr = clrGray; + } + + // + object.LowerColor(style.clr); + object.LowerWidth(style.width); + object.LowerStyle(style.style); + object.UpperRayLeft(false); + object.LowerRayRight(true); + } + + // + // Peak Pivots ... + style = defaultBearishStyle; + object.PeaksColor(style.clr); + object.PeaksWidth(style.width); + object.PeaksAnchor(ANCHOR_BOTTOM); + + // + // Vale Pivots ... + style = defaultBullishStyle; + object.ValesColor(style.clr); + object.ValesWidth(style.width); + object.ValesAnchor(ANCHOR_TOP); + + // + style.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/x-tmp-market-analyser.codes.mq5 b/BKPS/14041018/Documents/BKP/x-tmp-market-analyser.codes.mq5 new file mode 100644 index 0000000..14786e6 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/x-tmp-market-analyser.codes.mq5 @@ -0,0 +1,826 @@ + +/** + * Analyse Market based on Specified Bar ... + * + * @param forBar: XOHCL, reference Specified Bar for Analyse Market ... + * @param structure: XFIMAMarketStructure, reference to holds result ... + * @param config: XFIMAPatternDetectorConfig, reference to Configure Detector ... + */ +void AnalyseMarket( + XOHCL &forBar, + XFIMAMarketStructure &structure, + XFIMAPatternDetectorConfig &config // +) +{ + // + // Prepare ... + structure.Clean(); + + // + // Validate ... + if (!forBar.IsValid()) + { + return; + } + + // + // Do Analysis ... + + // + structure.bar = forBar; + + // + int idx = -1; + bool has = false; + int maxAllowedCollecting = 50; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Detecting POI Based on Config ... + + // + // Order Block ... + if (config.detectOB) + { + // + bool isOB = HasOB( + forBar, + iDir, + structure.ob, + config.obLoopback // + ); + bool isBullishOB = isOB && + IsSpecifiedBullish(iDir); + bool isBearishOB = isOB && + IsSpecifiedBearish(iDir); + if (!isOB) + { + structure.ob.Clean(); + } + + // + // Detect Touches ... + if (isOB) + { + // + AddIfNotExists( + structure.ob, + obs, + maxAllowedCollecting // + ); + + // + XOHCL pBar; + bool has = forBar.GetPreviousBar(pBar); + if (has) + { + // + structure.isOBTouched = + isBullishOB + ? pBar.low < structure.ob.upper + : pBar.high > structure.ob.lower; + } + + // + pBar.Clean(); + } + } + + // + // Fair Value Gap ... + if (config.detectFVG) + { + // + bool isFVG = HasFVG( + forBar, + iDir, + structure.fvg, + config.fvgLoopback // + ); + bool isBullishFVG = isFVG && + IsSpecifiedBullish(iDir); + bool isBearishFVG = isFVG && + IsSpecifiedBearish(iDir); + if (!isFVG) + { + structure.fvg.Clean(); + } + + // + // Detect Touches ... + if (isFVG) + { + // + AddIfNotExists( + structure.fvg, + fvgs, + maxAllowedCollecting // + ); + + // + XOHCL pBar; + bool has = forBar.GetPreviousBar(pBar); + if (has) + { + // + structure.isFVGTouched = + isBullishFVG + ? pBar.low < structure.fvg.upper + : pBar.high > structure.fvg.lower; + } + + // + pBar.Clean(); + } + } + + // + // Checking Momentum Bar ... + if (config.detectMomentum) + { + // + bool isMomentum = IsMomentumBar( + forBar, + iDir, + config.momentumBarRangeLength, + config.momentumBarApprovedMultiplier // + ); + bool isBullishMomentum = isMomentum && + IsSpecifiedBullish(iDir); + bool isBearishMomentum = isMomentum && + IsSpecifiedBearish(iDir); + if (isMomentum) + { + structure.momentumDir = iDir; + } + } + + // + // Checking Engulfed Bar ... + if (config.detectEngulfed) + { + // + bool isEngulfed = IsEngulfedBar( + forBar, + iDir // + ); + bool isBullishEngulfed = isEngulfed && + IsSpecifiedBullish(iDir); + bool isBearishEngulfed = isEngulfed && + IsSpecifiedBearish(iDir); + if (isEngulfed) + { + structure.engulfedDir = iDir; + } + } + + // + // Checking TruGaped Bar ... + if (config.detectTrueGaped) + { + // + bool isTrueGaped = IsTrueGapedBar( + forBar, + iDir, + config.truwGapApprovedPointMultiplier // + ); + bool isBullishTrueGaped = isTrueGaped && + IsSpecifiedBullish(iDir); + bool isBearishTrueGaped = isTrueGaped && + IsSpecifiedBearish(iDir); + if (isTrueGaped) + { + structure.trueGapedDir = iDir; + } + } + + // + // Checking Pinned Bar ... + if (config.detectPinned) + { + // + bool isPinned = IsPinnedBar( + forBar, + iDir, + config.pinnedBaarShadowApprovedMultiplier, + config.pinnedBarMinimumPinBarRangeMultiplier, + config.pinnedBarForceDirection // + ); + bool isBullishPinned = isPinned && + IsSpecifiedBullish(iDir); + bool isBearishPinned = isPinned && + IsSpecifiedBearish(iDir); + if (isPinned) + { + structure.pinnedDir = iDir; + } + } + + // + // Checking Star Pattern ... + if (config.detectStarPattern) + { + // + bool isStarPattern = IsStartPattern( + forBar, + iDir // + ); + bool isBullishStarPattern = isStarPattern && + IsSpecifiedBullish(iDir); + bool isBearishStarPattern = isStarPattern && + IsSpecifiedBearish(iDir); + if (isStarPattern) + { + structure.starPatternDir = iDir; + } + } + + // + // Checking Piercing Pattern ... + if (config.detectPiercingPattern) + { + // + bool isPiercingPattern = IsPiercingPattern( + forBar, + iDir // + ); + bool isBullishPiercingPattern = isPiercingPattern && + IsSpecifiedBullish(iDir); + bool isBearishPiercingPattern = isPiercingPattern && + IsSpecifiedBearish(iDir); + if (isPiercingPattern) + { + structure.piercingPatternDir = iDir; + } + } + + // + // Checking Rising Pattern ... + if (config.detectRisingPattern) + { + // + bool isRisingPattern = IsRisingPattern( + forBar, + iDir // + ); + bool isBullishRisingPattern = isRisingPattern && + IsSpecifiedBullish(iDir); + bool isBearishRisingPattern = isRisingPattern && + IsSpecifiedBearish(iDir); + if (isRisingPattern) + { + structure.risingPatternDir = iDir; + } + } + + // + // Checking Flag Pattern ... + if (config.detectFlagPattern) + { + // + XOHCL swingBar; + bool isFlagPattern = IsFlagPattern( + forBar, + iDir, + swingBar, + config.flagPatternMinimumPullbackBars // + ); + bool isBullishFlagPattern = isFlagPattern && + IsSpecifiedBullish(iDir); + bool isBearishFlagPattern = isFlagPattern && + IsSpecifiedBearish(iDir); + if (isFlagPattern) + { + // + structure.flagSwing = swingBar; + structure.flagPatternDir = iDir; + } + swingBar.Clean(); + } + + // + // Detect SignalKey Bar Pattern ... + if (config.detectSignalKeyBarPattern) + { + // + bool isSignalKeyBar = IsSignalKeyBarPattern( + forBar, + iDir, + config.signalKeyBarShadowApprovedMultiplier, + config.signalKeyBarMinimumPinBarRangeMultiplier, + config.signalKeyBarForceDirection // + ); + bool isBullishSignalKeyBar = isSignalKeyBar && + IsSpecifiedBullish(iDir); + bool isBearishSignalKeyBar = isSignalKeyBar && + IsSpecifiedBearish(iDir); + if (isSignalKeyBar) + { + structure.signalKeyBarPatternDir = iDir; + } + } + + // + // Detect Swing Trend ... + if (config.detectSwingTrend) + { + // + XOHCL swings[]; + bool hasSwingTrend = HasSwingTrend( + forBar, + iDir, + swings, + config.trendingNumberOfSwings, + config.trendingSwingShoulders // + ); + bool hasBullishSwingTrend = hasSwingTrend && + IsSpecifiedBullish(iDir); + bool hasBearishSwingTrend = hasSwingTrend && + IsSpecifiedBearish(iDir); + if (hasSwingTrend) + { + // + Copy( + swings, + structure.trendSwings // + ); + structure.trendDir = iDir; + } + SpecifiedClean(swings); + } + + // + // Detect Supports ... + if (config.detectSupport) + { + // + XOHCL support; + bool hasSupport = HasSupport( + forBar, + support, + config.supportAndResistanceValidationLength, + config.supportAndResistanceMaxAllowedLoopback // + ); + if (hasSupport) + { + // + XBoxZone supportBox; + has = ToSupportBox(support, supportBox); + + // + // Validate Zone Strength if Provided ... + if (config.minAllowdSupportAndResistanceStrength > 0) + { + // + has = has && + ValidateStrength( + supportBox, + config.minAllowdSupportAndResistanceStrength // + ); + } + + // + if (has) + { + // + AddIfNotExists( + supportBox, + supports, + maxAllowedCollecting // + ); + + // + structure.support = supportBox; + } + + // + // Check for Support Touches ... + XOHCL pBar; + has = has && + forBar.GetPreviousBar(pBar); + if (has) + { + structure.isSupportTouched = pBar.low < supportBox.upper; + } + + // + pBar.Clean(); + supportBox.Clean(); + } + support.Clean(); + } + + // + // Detect Resistance ... + if (config.detectResistance) + { + // + XOHCL resistance; + bool hasResistance = HasResistance( + forBar, + resistance, + config.supportAndResistanceValidationLength, + config.supportAndResistanceMaxAllowedLoopback // + ); + if (hasResistance) + { + // + XBoxZone resistanceBox; + has = ToResistanceBox(resistance, resistanceBox); + + // + // Validate Zone Strength if Provided ... + if (config.minAllowdSupportAndResistanceStrength > 0) + { + // + has = has && + ValidateStrength( + resistanceBox, + config.minAllowdSupportAndResistanceStrength // + ); + } + + // + if (has) + { + // + AddIfNotExists( + resistanceBox, + resistances, + maxAllowedCollecting // + ); + + // + structure.resistance = resistanceBox; + } + + // + // Check for Resistance Touches ... + XOHCL pBar; + has = has && + forBar.GetPreviousBar(pBar); + if (has) + { + structure.isResistanceTouched = pBar.high > resistanceBox.upper; + } + + // + pBar.Clean(); + resistanceBox.Clean(); + } + resistance.Clean(); + } + + // + // Analysers ... + + // + // Analyse Based on PV ... + if (config.analyseFIMAPVPivots) + { + // + XPivotAnalysis analysis; + has = AnalysePVPivots( + analysis, // Result ... + forBar.Index(), // Bar Index ... + config.numberOfRequiredPivotsForAnalysis, // Required Number of Pivots ... + config.maxAllowedLoopbackLengthForAnalysis, // Max Allowed Loopback ... + config.pvPivotsValidationLength // Validation Length ... + ); + if (has) + { + structure.pvAnalysis = analysis; + } + } + + // + // Analyse Based on MA ... + if (config.analyseFIMAMAPivots) + { + // + XPivotAnalysis analysis; + has = AnalyseMAPivots( + analysis, // Result ... + forBar.Index(), // Bar Index ... + config.numberOfRequiredPivotsForAnalysis, // Required Number of Pivots ... + config.maxAllowedLoopbackLengthForAnalysis, // Max Allowed Loopback ... + config.pvPivotsValidationLength // Validation Length ... + ); + if (has) + { + structure.maAnalysis = analysis; + } + } + + // + // Analyse Based on SAR ... + if (config.analyseFIMASARPivots) + { + // + XPivotAnalysis analysis; + has = AnalyseSARPivots( + analysis, // Result ... + forBar.Index(), // Bar Index ... + config.numberOfRequiredPivotsForAnalysis, // Required Number of Pivots ... + config.maxAllowedLoopbackLengthForAnalysis // Max Allowed Loopback ... + ); + if (has) + { + structure.sarAnalysis = analysis; + } + } + + // + // Analyse Based on ZigZag ... + if (config.analyseFIMAZigZagPivots) + { + // + XPivotAnalysis analysis; + has = AnalyseZigZagPivots( + analysis, // Result ... + forBar.Index(), // Bar Index ... + config.numberOfRequiredPivotsForAnalysis, // Required Number of Pivots ... + config.maxAllowedLoopbackLengthForAnalysis // Max Allowed Loopback ... + ); + if (has) + { + structure.zigzagAnalysis = analysis; + } + } + + // + // COMPLEX Actions ... + + // + // Lockup For Previous Zone ... + has = structure.isSupportTouched || + structure.isResistanceTouched; + if (has) + { + // + if (structure.isSupportTouched) + { + // + idx = GetYoungestBefore( + structure.support.from, + supports // + ); + has = IsValidIndex(idx); + if (has) + { + structure.prevZone = supports[idx]; + } + } + else if (structure.isResistanceTouched) + { + // + idx = GetYoungestBefore( + structure.resistance.from, + resistances // + ); + has = IsValidIndex(idx); + if (has) + { + structure.prevZone = resistances[idx]; + } + } + } + + // + // Detect Recently Tested Zones ... + if ((config.detectSupport || + config.detectResistance) && + config.recentlyTestedZonesMaxLookup > 0) + { + // + XOHCL iBar; + int idx = -1; + bool has = false; + + // + int start = forBar.Index() + 1; + int end = start + config.recentlyTestedZonesMaxLookup; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + has = forBar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Selecting Support and Resistances ... + + // + // Supports ... + idx = GetYoungestBefore(iBar.time, supports); + has = IsValidIndex(idx); + if (has) + { + // + // Check Testing ... + has = IsTested(iBar, supports[idx]); + if (has) + { + // + AddIfNotExists( + supports[idx], + structure.recentlyTestedZones // + ); + } + } + + // + // Resistances ... + idx = GetYoungestBefore(iBar.time, resistances); + has = IsValidIndex(idx); + if (has) + { + // + // Check Testing ... + has = IsTested(iBar, resistances[idx]); + if (has) + { + // + AddIfNotExists( + resistances[idx], + structure.recentlyTestedZones // + ); + } + } + } + } + + // + // Checkup for FakeBreaked Zones ... + if (config.detectSupport || + config.detectResistance) + { + // + // Retrieve Previous Bar ... + int idx = -1; + XOHCL pForBar; + XOHCL breakerBar; + XBoxZone pSupport; + XOHCL pBreakerBar; + XBoxZone pResistance; + + // + // Selecting Previously Touched Support / Resistance ... + has = forBar.GetPreviousBar(pForBar); + if (has) + { + // + // Detecting Nearest Above Lows Support ... + idx = GetYoungestAbove( + pForBar.low, + supports // + ); + has = IsValidIndex(idx) && + IsBreaked( + forBar, + supports[idx] // + ); + if (has) + { + pSupport = supports[idx]; + } + + // + // Detecting Nearest Below Highs Resistance ... + idx = GetYoungestBelow( + pForBar.high, + resistances // + ); + has = IsValidIndex(idx) && + IsBreaked( + forBar, + resistances[idx] // + ); + if (has) + { + pResistance = resistances[idx]; + } + } + + // + // Check at least a zone Exists ... + // Selecting pTestedZone ... + has = pSupport.IsValid() || + pResistance.IsValid(); + if (has) + { + // + // Support ... + has = pSupport.IsValid(); + if (has) + { + // + structure.isPTest = true; + structure.pTestedZone = pSupport; + } + + // + // Resistance ... + has = pResistance.IsValid(); + if (has) + { + // + structure.isPTest = true; + structure.pTestedZone = pResistance; + } + } + + // + // Check pTestedZone Existance ... + has = structure.isPTest && + structure.pTestedZone.IsValid(); + if (has) + { + // + // Get Breaker Bars ... + XOHCL breakerBars[]; + int breakerBarsCount = GetBreakerBars( + structure.pTestedZone, + breakerBars // + ); + has = IsValidSize(breakerBarsCount); + if (has) + { + // + idx = GetYoungestBar(breakerBars); + has = IsValidIndex(idx); + if (has) + { + breakerBar = breakerBars[idx]; + } + } + + // + SpecifiedClean(breakerBars); + } + + // + // Check Zone Breaker Bar Exists ... + // Validate Zone Fake Breake Langth ... + has = breakerBar.IsValid(); + if (has) + { + // + // Validate Breake Length ... + has = (breakerBar.Index() - pForBar.Index()) <= config.supportAndResistanceBreakeValidationLength; + } + + // + // Cleanup Resources ... + // + if (!has) + { + // + structure.isPTest = false; + structure.pTestedZone.Clean(); + } + pForBar.Clean(); + pSupport.Clean(); + breakerBar.Clean(); + pBreakerBar.Clean(); + pResistance.Clean(); + } +} + +// +// Lockup For Previous Zone ... +has = structure.isSupportTouched || + structure.isResistanceTouched; +if (has) +{ + // + if (structure.isSupportTouched) + { + // + idx = GetYoungestBefore( + structure.support.from, + supports // + ); + has = IsValidIndex(idx); + if (has) + { + structure.prevZone = supports[idx]; + } + } + else if (structure.isResistanceTouched) + { + // + idx = GetYoungestBefore( + structure.resistance.from, + resistances // + ); + has = IsValidIndex(idx); + if (has) + { + structure.prevZone = resistances[idx]; + } + } +} diff --git a/BKPS/14041018/Documents/BKP/xfima-zone-detector.bkp.mq5 b/BKPS/14041018/Documents/BKP/xfima-zone-detector.bkp.mq5 new file mode 100644 index 0000000..abc73a7 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/xfima-zone-detector.bkp.mq5 @@ -0,0 +1,1219 @@ + + // + // Detectors ... + + /** + * Detect Zones (Support / Resistance) based on XFIMA Validators ... + * + * @param zones: XBoxZone, reference to Collection for holding Detected Zones ... + * @param barIndex: int, Specified Start Looking Bar Index ... + * @param onlyValidZones: bool, Only Validation Zones ... + * @param requiredNumberOfZones: int, Specified how many zones looking for ... + * @param shadowMultiplier: double, a valid zone's Shadow side multiplier ... + * @param validationStrength: double, Validation Strength ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopbackLength: int, Specified Max Allowed Looping back trhough Bars for Detection ... + * + * @return ( int ) + */ + int DetectXFIMAZones( + XBoxZone &zones[], + int barIndex = 0, + bool onlyValidZones = false, + int requiredNumberOfZones = 50, + double shadowMultiplier = 4, + double validationStrength = 1, + int validationLength = 7, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(zones); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 3); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 2); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOfZones = NormalizeInt(requiredNumberOfZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + XOHCL bar; + bool has = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex + 1 // + ); + if (!has) + { + return result; + } + + // + // Define Requirements ... + XOHCL iBar; + XBoxZone iBox; + bool isBullish = false; + bool isBearish = false; + double iUpper = EMPTY_VALUE; + double iLower = EMPTY_VALUE; + double iHKUpper = EMPTY_VALUE; + double iHKLower = EMPTY_VALUE; + double iMAUpper = EMPTY_VALUE; + double iMALower = EMPTY_VALUE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Create a Loop to Detect Zones ... + int start = barIndex; + int idx = start - 1; + int end = start + maxAllowedLoopbackLength; + while (ArraySize(zones) < requiredNumberOfZones && idx < end) + { + // + idx++; + + // + // Initialize Indexed Bar ... + has = bar.BarAt(idx, iBar); + if (!has) + { + continue; + } + + // + // Reading Bars ... + iMAUpper = GetMABondUpper(idx); + iMALower = GetMABondLower(idx); + iHKUpper = GetHKBondUpper(idx); + iHKLower = GetHKBondLower(idx); + + // + iUpper = MathMax(iMAUpper, iHKUpper); + iLower = MathMin(iMALower, iHKLower); + + // + // Check Bar State ... + has = + NotEmptyZero(iUpper) && + NotEmptyZero(iLower); + if (!has) + { + continue; + } + + // + // Check Direction of Zone ... + isBullish = iBar.low < iLower; + isBearish = iBar.high > iUpper; + has = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!has) + { + continue; + } + + // + // Validate Price Based on Bar ... + // Validate Shadow Multiplier ... + has = + isBullish + ? iBar.low < bar.low + : iBar.high > bar.high; + has = + has && + (isBullish + ? iBar.GetLowShadow() > iBar.GetHighShadow() * shadowMultiplier + : iBar.GetHighShadow() > iBar.GetLowShadow() * shadowMultiplier); + if (!has) + { + continue; + } + + // + iDir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Fill Bax ... + iBox.dir = iDir; + iBox.symbol = mSymbol; + iBox.period = mPeriod; + iBox.upper = + isBullish + ? iBar.GetDown() + : iBar.high; + iBox.lower = + isBullish + ? iBar.low + : iBar.GetUp(); + iBox.type = + (isBullish ? "XFIMA_Support" : "XFIMA_Resistance") + "_" + + ToXString(NormalizePrice(iBox.upper, iBox.symbol)) + "_" + + ToXString(NormalizePrice(iBox.lower, iBox.symbol)); + + // + iBox.at = iBar.time; + iBox.to = bar.time; + + // + // Loopback to Detect From Time ... + XOHCL pBar; + datetime fromTime = NULL; + has = iBar.GetPreviousBar(pBar); + if (has) + { + // + while (!IsXValid(fromTime)) + { + // + // Check Price Inside ... + has = + isBullish + ? pBar.GetDown() < iBox.lower + : pBar.GetUp() > iBox.upper; + if (has) + { + fromTime = pBar.time; + } + + // + // Retrieve PrevBar ... + has = pBar.GetPreviousBar(pBar); + if (!has) + { + break; + } + } + } + has = IsXValid(fromTime); + if (has) + { + iBox.from = fromTime; + } + + // + // Validate Zone Length ... + has = iBox.IsValid() && + (validationStrength >= 1 + ? iBox.GetRange() >= validationStrength * GetPoints(iBox.symbol) + : true) && + (iBox.FromIndex() - iBox.AtIndex() >= validationLength); + + // + // Validate Zone State ... + if (has) + { + // + // Cleanup Bar ... + iBar.Clean(); + + // + // Loopingh through At Index ... + for (int i = iBox.ToIndex(); i < iBox.AtIndex(); i++) + { + // + // Initialized Indexed Bar ... + has = bar.BarAt(i, iBar); + if (!has) + { + break; + } + + // + // Validate Bar ... + has = + iBox.IsBullish() + ? iBar.low > iBox.lower + : iBar.high < iBox.upper; + if (!has) + { + break; + } + } + } + + // + if (has) + { + // + AddIfNotExists( + iBox, + zones // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iBox.Clean(); + } + + // + result = ArraySize(zones); + + // + // Cleanup Resources ... + if (!result) + { + XClean(zones); + } + bar.Clean(); + iBar.Clean(); + iBox.Clean(); + + // + return result; + } + + int DetecteXFIMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOfPivots = 50, + int validationLength = 7, + int maxAllowedLoopbackLength = 1500, // + // + // PV ... + int pvValidationLength = 7, + // + // Momentum ... + int momentumBarValidationLength = 3, + double momentumBarApprovedMultiplier = 3, + // + // TrueGap ... + double trueGapApprovedStrength = 2, + // + // Pin ... + double pinBarShadowApprovedMultiplier = 3, + double pinBarRangeMultiplier = 4, + bool pinBarForceDirection = false, + // + // Flag ... + int flagPatternPullbackLength = 3 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + requiredNumberOfPivots = NormalizeInt(requiredNumberOfPivots, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + pvValidationLength = NormalizeInt(pvValidationLength, 0); + + // + momentumBarValidationLength = NormalizeInt(momentumBarValidationLength, 2); + momentumBarApprovedMultiplier = NormalizeDouble(momentumBarApprovedMultiplier, 1); + + // + trueGapApprovedStrength = NormalizeDouble(trueGapApprovedStrength, 1); + + // + pinBarRangeMultiplier = NormalizeDouble(pinBarRangeMultiplier, 4); + pinBarShadowApprovedMultiplier = NormalizeDouble(pinBarShadowApprovedMultiplier, 3); + + // + flagPatternPullbackLength = NormalizeInt(flagPatternPullbackLength, 3); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XOHCL tmpBar; + XPivot iPivot; + int count = 0; + string iPrefix = NULL; + int idx = barIndex - 1; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + double iValue = EMPTY_VALUE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_DIRECTION tmpDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int end = barIndex + maxAllowedLoopbackLength; + while ( + idx < end && + ArraySize(pivots) < requiredNumberOfPivots) + { + // + idx++; + + // + iBar.Clean(); + iPivot.Clean(); + tmpBar.Clean(); + iPrefix = NULL; + iDir = X_DIRECTION_NONE; + + // + has = iBar.Init( + mSymbol, + mPeriod, + idx // + ); + if (!has) + { + break; + } + + // + // Pivots List ... + + // + // PV ... + bool isPV = false; + bool isPeak = false; + bool isVale = false; + tmpDir = X_DIRECTION_NONE; + if (pvValidationLength > 0) + { + // + isPV = patternDetector.IsPV( + iBar, + tmpDir, + pvValidationLength // + ); + isPeak = isPV && + IsXBearish(tmpDir); + isVale = isPV && + IsXBullish(tmpDir); + if (isPV) + { + iPrefix += isPeak ? "XPK" : "XVL"; + } + + // + // Continue Loopback if PV Validation Provided and not isPV ... + if (!isPV) + { + continue; + } + } + + // + // Momentum Bar ... + bool isMomentum = patternDetector.IsMomentumBar( + iBar, + iDir, + momentumBarValidationLength, + momentumBarApprovedMultiplier // + ); + if (isMomentum) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isMomentum = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "MNTM"; + } + } + + // + // Engulf Bar ... + bool isEngulfed = patternDetector.IsEngulfedBar( + iBar, + iDir // + ); + if (isEngulfed) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isEngulfed = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "ENGLF"; + } + } + + // + // True Gap ... + bool isTrueGaped = patternDetector.IsTrueGapedBar( + iBar, + iDir, + trueGapApprovedStrength // + ); + if (isTrueGaped) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isTrueGaped = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "TG"; + } + } + + // + // Pin Bar ... + bool isPinned = patternDetector.IsPinnedBar( + iBar, + iDir, + pinBarShadowApprovedMultiplier, + pinBarRangeMultiplier, + pinBarForceDirection // + ); + if (isPinned) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isPinned = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "PND"; + } + } + + // + // Patterns ... + + // + // Star Pattern ... + bool isStarPattern = patternDetector.IsStarPattern( + iBar, + iDir // + ); + if (isStarPattern) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isStarPattern = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "STR"; + } + } + + // + // Piercing Pattern ... + bool isPiercingPattern = patternDetector.IsPiercingPattern( + iBar, + iDir // + ); + if (isPiercingPattern) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isPiercingPattern = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "PRCG"; + } + } + + // + // Rising Pattern ... + bool isRisingPattern = patternDetector.IsRisingPattern( + iBar, + iDir // + ); + if (isRisingPattern) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isRisingPattern = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "RSG"; + } + } + + // + // Flag Pattern ... + bool isFlagPattern = patternDetector.IsFlagPattern( + iBar, + iDir, + tmpBar, + flagPatternPullbackLength // + ); + if (isFlagPattern) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isFlagPattern = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "FLG"; + } + } + + // + // Signal Key Pattern ... + bool isSignalKeyPattern = patternDetector.IsSignalKeyBarPattern( + iBar, + iDir, + pinBarShadowApprovedMultiplier, + pinBarRangeMultiplier, + pinBarForceDirection // + ); + if (isSignalKeyPattern) + { + // + if (!IsXValid(tmpDir)) + { + tmpDir = iDir; + } + + // + if (iDir != tmpDir) + { + isSignalKeyPattern = false; + } + else + { + // + count++; + iPrefix += (IsXValid(iPrefix) ? "_" : "") + "SKB"; + } + } + + // + has = + isPinned || + isMomentum || + isEngulfed || + isTrueGaped || + isStarPattern || + isFlagPattern || + isRisingPattern || + isPiercingPattern || + isSignalKeyPattern; + if (!has) + { + continue; + } + + // // + // // Validate Pivot Length ... + // // Validate Pivot vs XFIMA Values ... + // for (int i = iBar.Index(); i < iBar.Index() + validationLength; i++) + // { + // // + // tmpBar.Clean(); + // has = iBar.BarAt(i, tmpBar); + // if (!has) + // { + // break; + // } + + // // + // iMin = EMPTY_VALUE; + // iMax = EMPTY_VALUE; + // has = GetBoundaryValues( + // iMin, + // iMax, + // i // + // ); + + // // + // // Validate Bar vs TmpBar and Also Boundary Values ... + // has = + // has && + // (IsXBullish(iDir) + // ? + // // tmpBar.low < iMin && + // (tmpBar.low > iBar.low || + // tmpBar.GetDown() || iBar.GetDown()) + // : + // // tmpBar.high > iMax && + // (tmpBar.high < iBar.high || + // tmpBar.GetUp() < iBar.GetUp())); + // if (!has) + // { + // break; + // } + + // // + // iValue = IsXBullish(iDir) + // ? iBar.low + // : iBar.high; + + // // + // iType = IsXBullish(iDir) + // ? X_PIVOT_TYPE_VALE + // : X_PIVOT_TYPE_PEAK; + + // // + // tmpBar.Clean(); + // } + + // + has = IsXValid(iPrefix); + if (has) + { + // + iValue = IsXBullish(iDir) + ? iBar.low + : iBar.high; + + // + iType = IsXBullish(iDir) + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_PEAK; + + // + // Preparing Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + iBar.symbol, + iDir, + iBar.period, + iType // + ); + if (has) + { + // + iPivot.prefix = iPrefix; + + // + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + tmpBar.Clean(); + + // + result = ArraySize(pivots); + + // + return result; + } + + /** + * Detect XFIMA Based POI Bars ... + * + * @param bars: XOHCL, reference collection to holds detected bars ... + * @param dirs: ENUM_X_DIRECTION, reference collection to holds detected bars Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param forDir: ENUM_X_DIRECTION, specified which Direction of potential bars looking for ... + * @param requiredNumberOfBars: int, Specified how many bars looking for ... + * @param maxAllowedLoopbackLength: int, Specified Max Allowed Looping back trhough Bars for Detection ... + * @return ( int ) + */ + int DetectXFIMAPOIBars( + XOHCL &bars[], + ENUM_X_DIRECTION &dirs[], + int barIndex = 0, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int requiredNumberOfBars = 300, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(bars); + XClean(dirs); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex - 1; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + while (ArraySize(bars) < requiredNumberOfBars || + idx < maxAllowedLoopbackLength) + { + // + idx++; + has = iBar.Init( + mSymbol, + mPeriod, + idx // + ); + if (!has) + { + continue; + } + + // + has = GetBoundaryValues( + iMin, + iMax, + idx // + ); + if (!has) + { + continue; + } + + // + isBullish = iBar.low < iMin; + isBearish = iBar.high > iMax; + has = + !HasDirection(forDir) + ? ((isBullish && !isBearish) || + (isBearish && !isBullish)) + : IsXBullish(forDir) + ? (isBullish && !isBearish) + : (isBearish && !isBullish); + if (has) + { + // + iDir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + AddRef( + iBar, + bars // + ); + + // + Add( + iDir, + dirs // + ); + } + } + + // + result = ArraySize(bars); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + int DetectXFIMAReversalPOIBars( + XOHCL &bars[], + ENUM_X_DIRECTION &dirs[], + int barIndex = 0, + bool forceTouchBoundary = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int requiredNumberOfBars = 300, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(bars); + XClean(dirs); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Detect POI Bars ... + XOHCL decisionBars[]; + ENUM_X_DIRECTION decisionBarDirs[]; + int decisionBarsCount = DetectXFIMAPOIBars( + decisionBars, + decisionBarDirs, + barIndex, + forDir, + requiredNumberOfBars, + maxAllowedLoopbackLength // + ); + has = IsValidSize(decisionBarsCount); + if (!has) + { + // + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + bool isCond1Bullish = false; + bool isCond1Bearish = false; + for (int i = 0; i < decisionBarsCount; i++) + { + // + // Read Boundary Values ... + has = GetBoundaryValues(iMin, iMax, i); + if (!has) + { + continue; + } + + // + // Check Bar Decision Direction ... + isBullish = IsXBullish(decisionBarDirs[i]); + isBearish = IsXBearish(decisionBarDirs[i]); + + // + // Validate ... + + // + isCond1Bullish = decisionBars[i].IsBullish(); + + // + isCond1Bearish = decisionBars[i].IsBearish(); + + // + isBullish = + isBullish && + (isCond1Bullish); + + // + isBearish = + isBearish && + (isCond1Bearish); + + // + if (forceTouchBoundary) + { + // + isBullish = + isBullish && + (decisionBars[i].high > iMin || + decisionBars[i].GetUp() > iMin); + + // + isBearish = + isBearish && + (decisionBars[i].low < iMax || + decisionBars[i].GetDown() < iMax); + } + + // + has = + isBullish || + isBearish; + if (has) + { + // + AddRef( + decisionBars[i], + bars // + ); + + // + Add( + decisionBarDirs[i], + dirs // + ); + } + } + + // + result = ArraySize(bars); + + // + // Cleanup Resources ... + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + + int DetectXFIMAContinuationalPOIBars( + XOHCL &bars[], + ENUM_X_DIRECTION &dirs[], + int barIndex = 0, + bool forceTouchBoundary = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int requiredNumberOfBars = 300, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(bars); + XClean(dirs); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Detect POI Bars ... + XOHCL decisionBars[]; + ENUM_X_DIRECTION decisionBarDirs[]; + int decisionBarsCount = DetectXFIMAPOIBars( + decisionBars, + decisionBarDirs, + barIndex, + forDir, + requiredNumberOfBars, + maxAllowedLoopbackLength // + ); + has = IsValidSize(decisionBarsCount); + if (!has) + { + // + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + bool isCond1Bullish = false; + bool isCond1Bearish = false; + for (int i = 0; i < decisionBarsCount; i++) + { + // + // Read Indexed Bars Boundaries ... + has = GetBoundaryValues(iMin, iMax, decisionBars[i].Index()); + if (!has) + { + continue; + } + + // + // Make Direction Opposit ... + decisionBarDirs[i] = Opposit(decisionBarDirs[i]); + + // + isBullish = IsXBullish(decisionBarDirs[i]); + isBearish = IsXBearish(decisionBarDirs[i]); + + // + // Check Bar Validations ... + + // + // Cond 1 ... + + // + isCond1Bullish = + decisionBars[i].IsBearish() && + (decisionBars[i].low >= iMax || + (decisionBars[i].low <= iMax && + decisionBars[i].GetUp() >= iMax)); + + // + isCond1Bearish = + decisionBars[i].IsBullish() && + (decisionBars[i].high <= iMin || + (decisionBars[i].high >= iMin && + decisionBars[i].GetDown() <= iMin)); + + // + isBullish = + isBullish && + (isCond1Bullish); + + // + isBearish = + isBearish && + (isCond1Bearish); + + // + if (forceTouchBoundary) + { + // + isBullish = + isBullish && + (decisionBars[i].low >= iMax || + (decisionBars[i].low <= iMax && + decisionBars[i].GetUp() >= iMax)); + + // + isBearish = + isBearish && + (decisionBars[i].high <= iMin || + (decisionBars[i].high >= iMin && + decisionBars[i].GetDown() <= iMin)); + } + + // + has = + isBullish || + isBearish; + if (has) + { + // + AddRef( + decisionBars[i], + bars // + ); + + // + Add( + decisionBarDirs[i], + dirs // + ); + } + } + + // + result = MathMin(ArraySize(bars), ArraySize(dirs)); + + // + // Cleanup Resources ... + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } diff --git a/BKPS/14041018/Documents/BKP/xfima.ind.tmp.mq5 b/BKPS/14041018/Documents/BKP/xfima.ind.tmp.mq5 new file mode 100644 index 0000000..f83b06d --- /dev/null +++ b/BKPS/14041018/Documents/BKP/xfima.ind.tmp.mq5 @@ -0,0 +1,2648 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XFIMA +// 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 XFIMA Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +#define ShortName "XFIMA" + +// +// 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 fiboUpperZoneLevel = X_FIBO_LEVEL_236; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_764; // 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 = 21; // Slow MA Length +input int maBondLength = 21; // MA Bond Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode +input bool hkIgnoreShadows = true; // HK Remove noises +input int hkSmoothingLength = 21; // HK Smoothing Length +input ENUM_X_MA_METHOD hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showHK = true; // Show HK +input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showMABond = true; // Show MA Bond +input bool showHKBond = true; // Show HK Bond +input bool showZigZag = true; // Show ZigZag +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 44 +#property indicator_plots 16 + +// +// 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, clrLime, clrLime, clrLime // clrYellow, clrOrangeRed, clrGray +#property indicator_width1 3 + +// +// 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, clrRed, clrRed, clrRed // clrLime, clrRed, clrGray +#property indicator_width2 3 + +// +// 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 Middle ... + +// +#define fiboMiddleBufferIndex 9 +#define fiboMiddleBufferPlotIndex 6 +double fiboMiddleBuffer[]; + +// +#property indicator_label7 "FIBMID" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_width7 2 + +// +// FIBO Lower ... + +// +#define fiboLowerBufferIndex 10 +#define fiboLowerBufferPlotIndex 7 +double fiboLowerBuffer[]; + +// +#property indicator_label8 "FIBLO" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrMagenta +#property indicator_width8 2 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 11 +#define zigzagBufferPlotIndex 8 +double zigzagBuffer[]; + +// +#property indicator_label9 "XZG" +#property indicator_type9 DRAW_SECTION +#property indicator_color9 clrYellow +#property indicator_width9 2 + +// +// MA Upper ... + +// +#define maUpperBufferIndex 12 +#define maUpperBufferPlotIndex 9 +double maUpperBuffer[]; + +// +#property indicator_label10 "UpperMA" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrLime +#property indicator_width10 3 + +// +// MA Lower ... + +// +#define maLowerBufferIndex 13 +#define maLowerBufferPlotIndex 10 +double maLowerBuffer[]; + +// +#property indicator_label11 "LowerMA" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrRed +#property indicator_width11 3 + +// +// XHK ... + +// +#define hkOpenBufferIndex 14 +double hkOpenBuffer[]; + +// +#define hkHighBufferIndex 15 +double hkHighBuffer[]; + +// +#define hkLowBufferIndex 16 +double hkLowBuffer[]; + +// +#define hkCloseBufferIndex 17 +double hkCloseBuffer[]; + +// +#define hkColorBufferIndex 18 +double hkColorBuffer[]; + +// +#define hkBufferPlotIndex 11 +#property indicator_label12 "XHK Open;XHK High;XHK Low;XHK Close" +#property indicator_type12 DRAW_COLOR_CANDLES +#property indicator_color12 CLR_NONE, clrAqua, clrMagenta, clrGray + +// +#define hkBondUpperBufferIndex 19 +double hkBondUpperBuffer[]; + +// +#define hkBondUpperBufferPlotIndex 12 +#property indicator_label13 "UpperHK" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrAqua +#property indicator_width13 3 + +// +#define hkBondLowerBufferIndex 20 +double hkBondLowerBuffer[]; + +// +#define hkBondLowerBufferPlotIndex 13 +#property indicator_label14 "LowerHK" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrMagenta +#property indicator_width14 3 + +// +// XPB ... + +// +#define pbUpperBufferIndex 21 +double pbUpperBuffer[]; + +// +#define pbUpperBufferPlotIndex 14 +#property indicator_label15 "UpperPB" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrAqua +#property indicator_width15 3 + +// +#define pbLowerBufferIndex 22 +double pbLowerBuffer[]; + +// +#define pbLowerBufferPlotIndex 15 +#property indicator_label16 "LowerPB" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrMagenta +#property indicator_width16 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 22 + +// +// 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[]; + +// +// ZigZag ... + +// +#define highsBufferIndex mLastBufferIndex + 12 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 13 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 14 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 15 +double lowsTimeBuffer[]; + +// +// XHK Data ... + +// +#define hkRawHighBufferIndex mLastBufferIndex + 16 +double hkRawHighBuffer[]; + +// +#define hkRawOpenBufferIndex mLastBufferIndex + 17 +double hkRawOpenBuffer[]; + +// +#define hkRawLowBufferIndex mLastBufferIndex + 18 +double hkRawLowBuffer[]; + +// +#define hkRawCloseBufferIndex mLastBufferIndex + 19 +double hkRawCloseBuffer[]; + +// +// XPB ... + +// +#define pbRawUpperBufferIndex mLastBufferIndex + 20 +double pbRawUpperBuffer[]; + +// +#define pbRawLowerBufferIndex mLastBufferIndex + 21 +double pbRawLowerBuffer[]; + +// +// 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 maUpperHandler = INVALID_HANDLE; +int maLowerHandler = INVALID_HANDLE; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Requirements ... +CArrayObj mObjects; +XCPOIDrawer *mDrawer; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; +int zigzagRecalc = 3; // Number of last extremes for recalculation + +// +double lastZigZagPeak = 0; +datetime lastZigZagPeakTime = NULL; + +// +double lastZigZagVale = 0; +datetime lastZigZagValeTime = NULL; + +// +// 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); + IndicatorRelease(maUpperHandler); + IndicatorRelease(maLowerHandler); +} + +/** + * 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // 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); + int maUpperCalculatedBars = BarsCalculated(maUpperHandler); + int maLowerCalculatedBars = BarsCalculated(maLowerHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + maUpperCalculatedBars >= maxLength && + maLowerCalculatedBars >= 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); + int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maUpperBuffer); + int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maLowerBuffer); + + // + // SAR ... + int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + copiedMAUppers >= limit && + copiedMALowers >= 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 && + maBondLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + 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); + result = MathMax(result, maBondLength); + + // + 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); + + // + // Middle ... + ArraySetAsSeries(fiboMiddleBuffer, true); + SetIndexBuffer(fiboMiddleBufferIndex, fiboMiddleBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboMiddleBufferPlotIndex, 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); + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Bond ... + + // + ENUM_DRAW_TYPE maBondDrawType = showMABond ? DRAW_LINE : DRAW_NONE; + + // + // MA Upper Bond ... + + // + ArraySetAsSeries(maUpperBuffer, true); + SetIndexBuffer(maUpperBufferIndex, maUpperBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABond); + // PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBondDrawType); + + // PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + // PlotIndexSetDouble(maUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Lower Bond ... + + // + ArraySetAsSeries(maLowerBuffer, true); + SetIndexBuffer(maLowerBufferIndex, maLowerBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABond); + // PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBondDrawType); + + // PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + // PlotIndexSetDouble(maLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // XHK ... + + // + // XHK Color ... + ArraySetAsSeries(hkColorBuffer, true); + SetIndexBuffer(hkColorBufferIndex, hkColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkOpenBuffer, true); + SetIndexBuffer(hkOpenBufferIndex, hkOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkHighBuffer, true); + SetIndexBuffer(hkHighBufferIndex, hkHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkLowBuffer, true); + SetIndexBuffer(hkLowBufferIndex, hkLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkCloseBuffer, true); + SetIndexBuffer(hkCloseBufferIndex, hkCloseBuffer, INDICATOR_DATA); + + // + // XHK Bond ... + + // + ENUM_DRAW_TYPE hkBondDrawType = showHKBond ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(hkBondUpperBuffer, true); + SetIndexBuffer(hkBondUpperBufferIndex, hkBondUpperBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetInteger(hkBondUpperBufferPlotIndex, PLOT_SHOW_DATA, showHKBond); + // PlotIndexSetInteger(hkBondUpperBufferPlotIndex, PLOT_DRAW_TYPE, hkBondDrawType); + + // PlotIndexSetInteger(hkBondUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + // PlotIndexSetDouble(hkBondUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Lower ... + ArraySetAsSeries(hkBondLowerBuffer, true); + SetIndexBuffer(hkBondLowerBufferPlotIndex, hkBondLowerBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetInteger(hkBondLowerBufferPlotIndex, PLOT_SHOW_DATA, showHKBond); + // PlotIndexSetInteger(hkBondLowerBufferPlotIndex, PLOT_DRAW_TYPE, hkBondDrawType); + + // PlotIndexSetInteger(hkBondLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + // PlotIndexSetDouble(hkBondLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // XPB Bond ... + + // + // Upper ... + ArraySetAsSeries(pbUpperBuffer, true); + SetIndexBuffer(pbUpperBufferIndex, pbUpperBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetInteger(pbUpperBufferIndex, PLOT_SHOW_DATA, showMABond); + // PlotIndexSetInteger(pbUpperBufferIndex, PLOT_DRAW_TYPE, maBondDrawType); + + // PlotIndexSetInteger(pbUpperBufferIndex, PLOT_DRAW_BEGIN, 0); + // PlotIndexSetDouble(pbUpperBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // Lower ... + ArraySetAsSeries(pbLowerBuffer, true); + SetIndexBuffer(pbLowerBufferIndex, pbLowerBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetInteger(pbLowerBufferIndex, PLOT_SHOW_DATA, showMABond); + // PlotIndexSetInteger(pbLowerBufferIndex, PLOT_DRAW_TYPE, maBondDrawType); + + // PlotIndexSetInteger(pbLowerBufferIndex, PLOT_DRAW_BEGIN, 0); + // PlotIndexSetDouble(pbLowerBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // Data Buffers ... + + // + // CYCLES ... + + // + // SC ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + // MC ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + // LC ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); + + // + // HC ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_CALCULATIONS); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // XHK Data ... + + // + ArraySetAsSeries(hkRawHighBuffer, true); + SetIndexBuffer(hkRawHighBufferIndex, hkRawHighBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hkRawOpenBuffer, true); + SetIndexBuffer(hkRawOpenBufferIndex, hkRawOpenBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hkRawLowBuffer, true); + SetIndexBuffer(hkRawLowBufferIndex, hkRawLowBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hkRawCloseBuffer, true); + SetIndexBuffer(hkRawCloseBufferIndex, hkRawCloseBuffer, INDICATOR_CALCULATIONS); + + // + // XPB Bond ... + + // + // Upper ... + ArraySetAsSeries(pbRawUpperBuffer, true); + SetIndexBuffer(pbRawUpperBufferIndex, pbRawUpperBuffer, INDICATOR_CALCULATIONS); + + // + // Lower ... + ArraySetAsSeries(pbRawLowerBuffer, true); + SetIndexBuffer(pbRawLowerBufferIndex, pbRawLowerBuffer, 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; + + // + 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; + } + + // + // MA Bond Upper ... + maUpperHandler = iMA( + _Symbol, + _Period, + maBondLength, + 0, + maMethod, + PRICE_HIGH // + ); + result = maUpperHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Bond Lower ... + maLowerHandler = iMA( + _Symbol, + _Period, + maBondLength, + 0, + maMethod, + PRICE_LOW // + ); + result = maLowerHandler != 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 // + ); + + // + // XHK ... + CalculateHKBar( + 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; + + // // + // double iPBUpper = MathMax(open[barIndex], close[barIndex]); + // double iPBLower = MathMin(open[barIndex], close[barIndex]); + + // // + // pbRawUpperBuffer[barIndex] = iPBUpper; + // pbRawLowerBuffer[barIndex] = iPBLower; + + // // + // // Upper ... + // iMAOnBuffer( + // ratesTotal, + // prevCalculated, + // barIndex, + // maBondLength, + // pbRawUpperBuffer, + // pbUpperBuffer, + // ToXMaMethod(maMethod) // + // ); + + // // + // // Lower ... + // iMAOnBuffer( + // ratesTotal, + // prevCalculated, + // barIndex, + // maBondLength, + // pbRawLowerBuffer, + // pbLowerBuffer, + // ToXMaMethod(maMethod) // + // ); + + // + // 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, + fiboUpperZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboMid = GetFibonacciLevel( + iPeak, + iVale, + fiboMiddleZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboLo = GetFibonacciLevel( + iPeak, + iVale, + fiboLowerZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + fiboUpperBuffer[barIndex] = iFiboUp; + fiboMiddleBuffer[barIndex] = iFiboMid; + 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; +} + +/** + * 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 ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = zigzagDepth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < zigzagRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, zigzagDepth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, zigzagDepth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +// +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 + : hkOpenBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : hkCloseBuffer[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)); + + // + bool isBullish = iHKOpenValue < iHKCloseValue; + bool isBearish = iHKOpenValue > iHKCloseValue; + + // + if (hkIgnoreShadows) + { + // + iHKHighValue = isBullish + ? iHKCloseValue + : iHKOpenValue; + + // + iHKLowValue = isBullish + ? iHKOpenValue + : iHKCloseValue; + } + + // + // XHK Buffers ... + hkOpenBuffer[barIndex] = iHKOpenValue; + hkHighBuffer[barIndex] = iHKHighValue; + hkLowBuffer[barIndex] = iHKLowValue; + hkCloseBuffer[barIndex] = iHKCloseValue; + + // + // XHK Raw Bufferss ... + hkRawOpenBuffer[barIndex] = iHKOpenValue; + hkRawHighBuffer[barIndex] = iHKHighValue; + hkRawLowBuffer[barIndex] = iHKLowValue; + hkRawCloseBuffer[barIndex] = iHKCloseValue; + + // + // Smoothing ... + if (IsXValid(hkSmoothingMode) && hkSmoothingLength > 0) + { + // + // XHK Signal ... + + // + // High ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawHighBuffer, + hkHighBuffer, + hkSmoothingMode // + ); + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawOpenBuffer, + hkOpenBuffer, + hkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawLowBuffer, + hkLowBuffer, + hkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawCloseBuffer, + hkCloseBuffer, + hkSmoothingMode // + ); + } + + // + hkBondUpperBuffer[barIndex] = hkHighBuffer[barIndex]; + hkBondLowerBuffer[barIndex] = hkLowBuffer[barIndex]; + + // + // Calculate HK Color ... + double iHKColorValue = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + hkColorBuffer[barIndex] = + showHK + ? iHKColorValue + : hideColorIDX; +} + +// +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(); +} + +// +// +// + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/BKP/xfima.poi.analysis.tmp.code.mq5 b/BKPS/14041018/Documents/BKP/xfima.poi.analysis.tmp.code.mq5 new file mode 100644 index 0000000..09b58b2 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/xfima.poi.analysis.tmp.code.mq5 @@ -0,0 +1,641 @@ +// // +// // Detect At lease Two PEAK and Two Vale ... +// XZigZagPoint tmpPoints[]; +// Copy( +// points, +// tmpPoints // +// ); + +// // +// // Detect Highs ... + +// // +// // Highest High ... + +// // +// XZigZagPoint iZGPeak1; +// XZigZagPoint iZGPeak2; + +// // +// // First ... +// int idx = GetHighest( +// tmpPoints, +// X_ZIGZAG_POINT_TYPE_PEAK // +// ); +// result = IsValidIndex(idx); +// if (!result) +// { +// // +// Clean(); +// iZGPeak1.Clean(); +// iZGPeak2.Clean(); +// SpecifiedClean(tmpPoints); + +// // +// return result; +// } +// iZGPeak1 = tmpPoints[idx]; +// ArrayRemove( +// tmpPoints, +// idx, +// 1 // +// ); + +// // +// // Second ... +// idx = GetHighest( +// tmpPoints, +// X_ZIGZAG_POINT_TYPE_PEAK // +// ); +// result = IsValidIndex(idx); +// if (!result) +// { +// // +// Clean(); +// iZGPeak1.Clean(); +// iZGPeak2.Clean(); +// SpecifiedClean(tmpPoints); + +// // +// return result; +// } +// iZGPeak2 = tmpPoints[idx]; +// ArrayRemove( +// tmpPoints, +// idx, +// 1 // +// ); + +// // +// // Detect Lows ... + +// // +// XZigZagPoint iZGVale1; +// XZigZagPoint iZGVale2; + +// // +// // First ... +// idx = GetLowest( +// tmpPoints, +// X_ZIGZAG_POINT_TYPE_VALE // +// ); +// result = IsValidIndex(idx); +// if (!result) +// { +// // +// Clean(); +// iZGPeak1.Clean(); +// iZGPeak2.Clean(); +// iZGVale1.Clean(); +// iZGVale2.Clean(); +// SpecifiedClean(tmpPoints); + +// // +// return result; +// } +// iZGVale1 = tmpPoints[idx]; +// ArrayRemove( +// tmpPoints, +// idx, +// 1 // +// ); + +// // +// // Second ... +// idx = GetLowest( +// tmpPoints, +// X_ZIGZAG_POINT_TYPE_VALE // +// ); +// result = IsValidIndex(idx); +// if (!result) +// { +// // +// Clean(); +// iZGPeak1.Clean(); +// iZGPeak2.Clean(); +// iZGVale1.Clean(); +// iZGVale2.Clean(); +// SpecifiedClean(tmpPoints); + +// // +// return result; +// } +// iZGVale2 = tmpPoints[idx]; +// ArrayRemove( +// tmpPoints, +// idx, +// 1 // +// ); + +// // +// // Check Directions ... +// bool isBullish = +// // +// (iZGPeak1.time > iZGPeak2.time && +// iZGVale1.time < iZGVale2.time) +// // +// ; +// bool isBearish = +// // +// (iZGPeak1.time < iZGPeak2.time && +// iZGVale1.time > iZGVale2.time) +// // +// ; +// result = +// (isBullish && !isBearish) || +// (isBearish && !isBullish); +// if (!result) +// { +// // +// Clean(); +// iZGPeak1.Clean(); +// iZGPeak2.Clean(); +// iZGVale1.Clean(); +// iZGVale2.Clean(); +// SpecifiedClean(tmpPoints); + +// // +// return result; +// } + +// // +// // Setting Direction ... +// dir = +// isBullish +// ? X_DIRECTION_BULLISH +// : isBearish +// ? X_DIRECTION_BEARISH +// : X_DIRECTION_NONE; + +// // +// // Setting Points ... +// Copy( +// points, +// pivots // +// ); + +// +// Cleanup Resources ... +// iZGPeak1.Clean(); +// iZGPeak2.Clean(); +// iZGVale1.Clean(); +// iZGVale2.Clean(); +// SpecifiedClean(tmpPoints); + +/** + * Analyse Market Structure ... + * + * @param bar: XOHCL, Specified Bar ... + * @param _pivots: XZigZagPivot, Specified ZigZag Points Collection ... + * + * @return ( bool ) + */ +bool Analyse( + XOHCL &bar, + XZigZagPivot &_pivots[] // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasChild(_pivots) && + bar.symbol == _pivots[0].symbol; + if (!result) + { + // + Clean(); + return result; + } + + // + // AssignSymbol and Period ... + time = bar.time; + symbol = bar.symbol; + period = bar.period; + Copy(_pivots, pivots); + + // + // Calculate Peaks and Vales Regressions ... + + // + // Peaks Processing ... + double mPeak = 0; + double bPeak = 0; + result = ValidateZigZagPivots( + mPeak, + bPeak, + _pivots, + X_ZIGZAG_PIVOT_TYPE_PEAK // + ); + + // + // Vales Processing ... + double mVale = 0; + double bVale = 0; + result = + result && + ValidateZigZagPivots( + mVale, + bVale, + _pivots, + X_ZIGZAG_PIVOT_TYPE_VALE // + ); + if (!result) + { + // + Clean(); + // SpecifiedClean(recentPeaks); + // SpecifiedClean(recentVales); + + // + return result; + } + + // // + // // Extracting Pivots ... + // int numberOfPivots = 2; + + // // + // // Reading Recent Peaks ... + // XZigZagPivot recentPeaks[]; + // int recentPeaksCount = GetRecent( + // _pivots, + // recentPeaks, + // numberOfPivots, + // X_ZIGZAG_PIVOT_TYPE_PEAK // + // ); + + // // + // // Reading Recent Vales ... + // XZigZagPivot recentVales[]; + // int recentValesCount = GetRecent( + // _pivots, + // recentVales, + // numberOfPivots, + // X_ZIGZAG_PIVOT_TYPE_VALE // + // ); + + // // + // // Validate Pivots ... + // result = + // recentPeaksCount >= numberOfPivots && + // recentValesCount >= numberOfPivots; + // if (!result) + // { + // // + // Clean(); + // SpecifiedClean(recentPeaks); + // SpecifiedClean(recentVales); + + // // + // return result; + // } + + // // + // // Detect Direction ... + + // // + // int zIdx = 0; + // int pIdx = numberOfPivots - 1; + + // // + // bool isBullish = + // recentPeaks[zIdx].value > recentPeaks[pIdx].value && + // recentVales[zIdx].value > recentVales[pIdx].value; + + // // + // bool isBearish = + // recentPeaks[zIdx].value < recentPeaks[pIdx].value && + // recentVales[zIdx].value < recentVales[pIdx].value; + + // // + // result = isBullish || isBearish; + // if (!result) + // { + // // + // Clean(); + // SpecifiedClean(recentPeaks); + // SpecifiedClean(recentVales); + + // // + // return result; + // } + + // // + // dir = + // isBullish + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // + // Calculate Support and Resistance ... + + // + // Validate ... + result = IsValid(); + if (!result) + { + Clean(); + } + + // + // SpecifiedClean(recentPeaks); + // SpecifiedClean(recentVales); + + // + return result; +} + +bool ValidateZigZagPivots( + double &_pivot, + double &_processed, + XZigZagPivot &_pivots[], + ENUM_X_ZIGZAG_POINT_TYPE _type // +) +{ + // + bool result = false; + + // + // Prepare ... + _pivot = 0; + _processed = 0; + + // + // Validate ... + result = HasChild(_pivots); + if (!result) + { + return result; + } + + // + // Define Required Variables for Calculations ... + double sumT = 0; + double sumP = 0; + double sumTP = 0; + double sumT2 = 0; + bool has = false; + int typeCount = 0; + + // + // Loop Through Pivots to Calculate Specified + // Type Pivots Summaries ... + int count = ArraySize(_pivots); + for (int i = 0; i < count; i++) + { + // + // Check Type Passed ... + has = + !IsXValid(_type) + ? true + : _type == _pivots[i].type; + if (!has) + { + continue; + } + + // + typeCount++; + double iP = _pivots[i].value; + double iT = (double)_pivots[i].time; + + // + sumT += iT; + sumP += iP; + sumTP += iT * iP; + sumT2 += iT * iP; + } + + // + // Calculate Process Values ... + double denominator = typeCount * sumT2 - sumT * sumT; + if (denominator != 0) + { + // + _pivot = (typeCount * sumTP - sumT * sumP) / denominator; + _processed = (sumP - _pivot * sumT) / typeCount; + } + else + { + _processed = sumP / typeCount; + } + + // + // Validating Result ... + result = _pivot > 0 && + _processed > 0; + + // + return result; +} + +/** + * Analyse Market Structure ... + * + * @param bar: XOHCL, Specified Bar ... + * @param _pivots: XZigZagPivot, Specified ZigZag Points Collection ... + * + * @return ( bool ) + */ +bool Analyse( + XOHCL &bar, + XZigZagPivot &_pivots[] // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasChild(_pivots) && + bar.symbol == _pivots[0].symbol; + if (!result) + { + // + Clean(); + return result; + } + + // + // Assign Requirements ... + + // + time = bar.time; + symbol = bar.symbol; + period = bar.period; + Copy(_pivots, pivots); + + // + int oldestPeakIdx = GetOldest(pivots, X_ZIGZAG_PIVOT_TYPE_PEAK); + int oldestValeIdx = GetOldest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE); + int youngestPeakIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_PEAK); + int youngestValeIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE); + + // + // Calculate Peaks and Vales Regressions ... + + // + // Peaks Processing ... + double mPeak = 0; + double bPeak = 0; + bool hasPeak = ValidateZigZagPivots( + mPeak, + bPeak, + pivots, + X_ZIGZAG_PIVOT_TYPE_PEAK // + ); + + // + // Vales Processing ... + double mVale = 0; + double bVale = 0; + bool hasVale = ValidateZigZagPivots( + mVale, + bVale, + pivots, + X_ZIGZAG_PIVOT_TYPE_VALE // + ); + + // + // Validate Calculated requirements ... + result = + (hasPeak || hasVale) && + (IsValidIndex(oldestPeakIdx) && + IsValidIndex(oldestValeIdx) && + IsValidIndex(youngestPeakIdx) && + IsValidIndex(youngestValeIdx)); + if (!result) + { + // + Clean(); + return result; + } + + // + // Calculating Values ... + + // + peakToTime = pivots[youngestPeakIdx].time; + peakFromTime = pivots[oldestPeakIdx].time; + + // + valeToTime = pivots[youngestValeIdx].time; + valeFromTime = pivots[oldestValeIdx].time; + + // + // Check Different Senarios ... + // 1-Valid Peak and Valid Vale Exists ... + if (hasPeak && hasVale) + { + // + // When Slopes Have same Sign, Use Average Slope for Parallel Lines ... + if (mPeak * mVale > 0) + { + // + // Calculating Parallel Slopes ... + double slopeParallel = (mPeak + mVale) / 2; + double bParallelPeak = pivots[youngestPeakIdx].value - slopeParallel * (double)peakToTime; + double bParallelVale = pivots[youngestValeIdx].value - slopeParallel * (double)valeToTime; + + // + // Peak ... + peakTo = slopeParallel * (double)peakToTime + bParallelPeak; + peakFrom = slopeParallel * (double)peakFromTime + bParallelPeak; + + // + // Vale ... + valeTo = slopeParallel * (double)valeToTime + bParallelVale; + valeFrom = slopeParallel * (double)valeFromTime + bParallelVale; + } + else + // + // separate trendlines if slopes differ ... + { + // + // Peak ... + peakTo = mPeak * (double)peakToTime + bPeak; + peakFrom = mPeak * (double)peakFromTime + bPeak; + + // + // Vale ... + valeTo = mVale * (double)valeToTime + bVale; + valeFrom = mVale * (double)valeFromTime + bVale; + } + } + else + // + // Only one of them Exists ... + { + // + // Valid Peak ... + if (hasPeak) + { + // + // Peak ... + peakTo = mPeak * (double)peakToTime + bPeak; + peakFrom = mPeak * (double)peakFromTime + bPeak; + } + + // + // Valid Vale ... + if (hasVale) + { + // + // Vale ... + valeTo = mVale * (double)valeToTime + bVale; + valeFrom = mVale * (double)valeFromTime + bVale; + } + } + + // + // Detecting Direction ... + + // + bool isBullish = + valeTo > valeFrom || + (valeTo > valeFrom && + peakTo > peakFrom); + + // + bool isBearish = + peakTo < peakFrom || + (peakTo < peakFrom && + valeTo < valeFrom); + + // + // Validate When Only One Direction Exists ... + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + // + Clean(); + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Calculate Support and Resistance ... + + // + // Validate ... + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; +} diff --git a/BKPS/14041018/Documents/BKP/xfima.signaller.tmp.codes.mq5 b/BKPS/14041018/Documents/BKP/xfima.signaller.tmp.codes.mq5 new file mode 100644 index 0000000..3c487b1 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/xfima.signaller.tmp.codes.mq5 @@ -0,0 +1,511 @@ +// +// Testing Bar Zones ... +// XBoxZone barZones[]; +// int barCounts = fima2Signaller.fimaHelper.ExtractBarZones( +// barZones, +// 1, // Bar Index ... +// 50, // Number of Zones ... +// 3, // Break Validation Length ... +// true, // Validate Fake Breakes ... +// 5, // Shadow Multiplier ... +// 1, // Strength ... +// 14 // Validation Length ... +// ); +// if (IsValidSize(barCounts)) +// { +// // +// // XCBoxObject *iObj; +// // for (int i = 0; i < barCounts; i++) +// // { +// // // +// // iObj = NULL; +// // bool isCreated = fima2Signaller.poiDrawer.DrawBox( +// // barZones[i], +// // iObj, +// // true, // Ignore At ... +// // barZones[i].type // Name ... +// // ); + +// // // +// // ZeroMemory(iObj); +// // } + +// // // +// // Print("Bar Zones Detected ..."); +// } + +// +// Testing HK Zones ... +// XBoxZone hkZones[]; +// int hkCounts = fima2Signaller.fimaHelper.ExtractHKZones( +// hkZones, +// 1, // Bar Index ... +// 50, // Number of Zones ... +// 5, // Shadow Multiplier ... +// 1, // Strength ... +// 14 // Validation Length ... +// ); +// if (IsValidSize(hkCounts)) +// { +// // // +// // XCBoxObject *iObj; +// // for (int i = 0; i < hkCounts; i++) +// // { +// // // +// // iObj = NULL; +// // bool isCreated = fima2Signaller.poiDrawer.DrawBox( +// // hkZones[i], +// // iObj, +// // true, // Ignore At ... +// // hkZones[i].type // Name ... +// // ); + +// // // +// // ZeroMemory(iObj); +// // } + +// // // +// // Print("HK Zones Detected ..."); +// } + +// +// Testing XFIMA MA Pivots ... +// XPivot maPivots[]; +// int maPivotsCount = fimaHelper.ExtractMAPivots( +// maPivots, +// 1, // Bar Index ... +// 50, // Number of Pivots ... +// 1 // Validation Diff ... +// ); +// if (IsValidSize(maPivotsCount)) +// { +// // +// // CArrayObj *iPivotsObj; +// // maPivotsCount = poiDrawer.DrawPivots( +// // maPivots, +// // iPivotsObj // +// // ); + +// // +// // Print("MA Pivots Detected ..."); +// } + +// +// Custom Indicator Direction Shifts ... +bool hasMACross = HasDirection(structure.maCrossDir); +bool hasHKSwitch = HasDirection(structure.hkSwitchDir); +bool hasSARSwitch = HasDirection(structure.sarSwitchDir); + +// +// Check Required Pattern Exists ... +bool hasPinnedBar = HasDirection(structure.pinnedDir); +bool hasEngulfedBar = HasDirection(structure.engulfedDir); +bool hasFlagPattern = HasDirection(structure.flagPatternDir); +bool hasStarPattern = HasDirection(structure.starPatternDir); +bool hasRisingPattern = HasDirection(structure.risingPatternDir); +bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); +bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + +// +// Check Bar Pattern Exists ... +// and Select Pattern Direction and Price and Price Type ... +has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; +if (has) +{ + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate Calculations ... + has = HasDirection(iDir) && + (isBullish || + isBearish) && + NotEmptyZero(iPrice) && + NotEmptyZero(iPriceEdge) && + iPrice != iPriceEdge; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } +} + +// +// Disable Signallers ... + +has = false; +// Strategy 1 ... +// Works on Support or Resistances Areas ... +// has = Strategy1HasSignal( +// bar, +// iZone, +// iName, +// supports, +// resistances, +// iDir, +// structure, +// fimaConditions // +// ); + +// +// Do all Draws Here ... +bool canDraw = false; +if (canDraw && has) +{ + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceEdgeType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } +} + +///////////////////////////////////////////////// + +/** + * Check Pattern Has Signal Based on Strategy 2 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ +bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions, + XFIMAMarketStructure &fimaMarketStructure // +) +{ + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + + // + // Validate ... + + // + // Do Detection ... + + // + // Validate result ... + + // + // Cleanup Resources ... + + // + return result; +} + +/** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ +bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &iZone, + XBoxZone &supports[], + XBoxZone &resistances[], + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions // +) +{ + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Reading XHK ... + + // + // Bar 1 ... + double cHKO = fimaConditions.hkOpenBuffer[0]; + double cHKH = fimaConditions.hkHighBuffer[0]; + double cHKL = fimaConditions.hkLowBuffer[0]; + double cHKC = fimaConditions.hkCloseBuffer[0]; + + // + // Bar 2 ... + double pHKO = fimaConditions.hkOpenBuffer[1]; + double pHKH = fimaConditions.hkHighBuffer[1]; + double pHKL = fimaConditions.hkLowBuffer[1]; + double pHKC = fimaConditions.hkCloseBuffer[1]; + + // + bool isCHKBullish = cHKO < cHKC; + bool isCHKBearish = cHKO > cHKC; + + // + bool isPHKBullish = pHKO < pHKC; + bool isPHKBearish = pHKO > pHKC; + + // + bool isCHKSwitchedToBullish = isCHKBullish && !isPHKBullish; + bool isCHKSwitchedToBearish = isCHKBearish && !isPHKBearish; + + // + return result; +} diff --git a/BKPS/14041018/Documents/BKP/xfima.tmp.codes.poi.mq5 b/BKPS/14041018/Documents/BKP/xfima.tmp.codes.poi.mq5 new file mode 100644 index 0000000..2451c73 --- /dev/null +++ b/BKPS/14041018/Documents/BKP/xfima.tmp.codes.poi.mq5 @@ -0,0 +1,916 @@ + +/** + * Leg Pattern Detection ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zone: XBoxZone, reference to Holds Detection Zone ... + * @param validationLength: int, leg minimum Validation Length ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool IsLegPattern( + XOHCL &bar, + XLeg &leg, + int validationLength = 3, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Prepare ... + leg.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 5); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Prepare Patterns Analysis Config ... + XPatternAnalysisConfig iPatternsConfig; + iPatternsConfig.Default(); + iPatternsConfig.CleanPatterns(); + iPatternsConfig.AddPattern(X_BAR_PATTERN_LOW); + iPatternsConfig.AddPattern(X_BAR_PATTERN_HIGH); + iPatternsConfig.AddPattern(X_BAR_PATTERN_FLAG); + iPatternsConfig.AddPattern(X_BAR_PATTERN_STAR); + iPatternsConfig.AddPattern(X_BAR_PATTERN_RISING); + iPatternsConfig.AddPattern(X_BAR_PATTERN_PIERCING); + iPatternsConfig.AddPattern(X_BAR_PATTERN_ENGULFED); + iPatternsConfig.AddPattern(X_BAR_PATTERN_MOMENTUM); + iPatternsConfig.AddPattern(X_BAR_PATTERN_SIGNALKEY); + iPatternsConfig.AddPattern(X_BAR_PATTERN_TRUE_GAPED); + + // + XOHCL iBar; + XOHCL pBar; + XOHCL iZBar; + XBoxZone zone; + XBoxZone iZone; + XBoxZone jZone; + bool has = false; + XBoxZone supports[]; + XOHCL bullishBars[]; + XOHCL bearishBars[]; + XBoxZone bullishFVGs[]; + XBoxZone bearishFVGs[]; + bool isBullish = false; + bool isBearish = false; + XBoxZone resistances[]; + double bullishPower = 0; + double bearishPower = 0; + int bullishBarsCount = 0; + int bearishBarsCount = 0; + int barIndex = bar.Index(); + int start = barIndex + 1; + XPatternAnalysis iPattern; + int end = start + loopback; + XPatternAnalysis patterns[]; + int bullishPatternsCount = 0; + int bearishPatternsCount = 0; + int sequentialsBullishBarsCount = 0; + int sequentialsBearishBarsCount = 0; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + for (int i = end; i >= start; i--) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + pBar.Clean(); + result = bar.BarAt(i, iBar); + result = result && + iBar.GetPreviousBar(pBar); + if (!result) + { + break; + } + + // + // Fill Bar Direction ... + isBullish = iBar.IsBullish(); + isBearish = iBar.IsBearish(); + + // + // Directional ... + + // + if (isBullish) + { + // + bullishBarsCount++; + + // + bullishPower += iBar.GetBody(); + bullishPower += iBar.GetLowShadow(); + bullishPower -= iBar.GetHighShadow(); + + // + AddIfNotExists(iBar, bullishBars); + } + + // + if (isBearish) + { + // + bearishBarsCount++; + + // + bearishPower += iBar.GetBody(); + bearishPower -= iBar.GetLowShadow(); + bearishPower += iBar.GetHighShadow(); + + // + AddIfNotExists(iBar, bearishBars); + } + + // + // Sequentail .... + + // + // Bullish ... + if (isBullish) + { + // + if (pBar.IsBullish()) + { + sequentialsBullishBarsCount++; + } + else if (pBar.IsBearish()) + { + sequentialsBullishBarsCount = 0; + } + } + + // + // Bearish ... + if (isBearish) + { + // + if (pBar.IsBearish()) + { + sequentialsBearishBarsCount++; + } + else if (pBar.IsBullish()) + { + sequentialsBearishBarsCount = 0; + } + } + + // + // Detect Patterns ... + iPattern.Clean(); + has = AnalyseBarPatterns(iBar, iPattern, iPatternsConfig); + if (has) + { + // + AddRef(iPattern, patterns); + + // + bullishPatternsCount += iPattern.Count(X_DIRECTION_BULLISH); + bearishPatternsCount += iPattern.Count(X_DIRECTION_BEARISH); + } + + // + // FVG Detection ... + CleanDirection(iDir); + has = HasFVG(iBar, iDir, iZone); + if (has) + { + // + if (iZone.IsBullish()) + { + AddIfNotExists(iZone, bullishFVGs); + } + else + { + AddIfNotExists(iZone, bearishFVGs); + } + } + + // + // Support / Resistance Detection ... + has = HasSupportResistance( + iBar, + iZone, + jZone, + 5 // + ); + if (has) + { + // + if (iZone.IsValid()) + { + AddIfNotExists(iZone, supports); + } + + // + if (jZone.IsValid()) + { + AddIfNotExists(jZone, resistances); + } + } + } + + // + // Summarizing ... + + // + // Detect Direction ... + zone.Clean(); + isBullish = false; + isBearish = false; + CleanDirection(iDir); + + // + isBullish = + // + bullishPower > 0 && + bullishBarsCount > 0 && + bullishPatternsCount > 0 && + sequentialsBullishBarsCount > 0 && + // + bullishPower > bearishPower && + bullishBarsCount > bearishBarsCount && + bullishPatternsCount > bearishPatternsCount && + sequentialsBullishBarsCount > sequentialsBearishBarsCount + // + ; + + // + isBearish = + // + bearishPower > 0 && + bearishBarsCount > 0 && + bearishPatternsCount > 0 && + sequentialsBearishBarsCount > 0 && + // + bearishPower > bullishPower && + bearishBarsCount > bullishBarsCount && + bearishPatternsCount > bullishPatternsCount && + sequentialsBearishBarsCount > sequentialsBullishBarsCount + // + ; + + // + // Validate ... + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + + // + // PRICE Types ... + ENUM_X_PRICE lowerPriceType = X_PRICE_LOW; + ENUM_X_PRICE upperPriceType = X_PRICE_HIGH; + + // + // Prepare Zone ... + if (result) + { + // + zone.at = bar.time; + zone.to = bar.time; + zone.period = bar.period; + zone.symbol = bar.symbol; + + // + zone.type = ToXString(X_BAR_PATTERN_LEG); + zone.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + int idx = -1; + if (isBullish) + { + idx = GetOldest(bullishBars); + } + else + { + idx = GetOldest(bearishBars); + } + + // + result = IsValidIndex(idx); + if (result) + { + // + iZBar.Clean(); + if (isBullish) + { + iZBar = bullishBars[idx]; + } + else + { + iZBar = bearishBars[idx]; + } + + // + zone.from = iZBar.time; + + // + iZBar.Clean(); + } + + // + if (isBullish) + { + // + // Prepare Upper and Lower ... + + // + // Upper ... + idx = GetHighestBarPrice(bullishBars, upperPriceType); + if (IsValidIndex(idx)) + { + zone.upper = bullishBars[idx].GetPrice(upperPriceType); + } + + // + // Lower ... + idx = GetLowestBarPrice(bullishBars, upperPriceType); + if (IsValidIndex(idx)) + { + zone.lower = bullishBars[idx].GetPrice(lowerPriceType); + } + } + else + { + // + // Prepare Upper and Lower ... + + // + // Upper ... + idx = GetHighestBarPrice(bearishBars, upperPriceType); + if (IsValidIndex(idx)) + { + zone.upper = bearishBars[idx].GetPrice(upperPriceType); + } + + // + // Lower ... + idx = GetLowestBarPrice(bearishBars, upperPriceType); + if (IsValidIndex(idx)) + { + zone.lower = bearishBars[idx].GetPrice(lowerPriceType); + } + } + + // + result = zone.IsValid(); + } + + // + // Prepare XLeg ... + if (result) + { + // + leg.dir = zone.dir; + leg.time = zone.from; + leg.upper = zone.upper; + leg.lower = zone.lower; + leg.symbol = zone.symbol; + leg.period = zone.period; + Copy(patterns, leg.patterns); + Copy(supports, leg.supports); + Copy(bullishBars, leg.bullishBars); + Copy(bearishBars, leg.bearishBars); + Copy(resistances, leg.resistances); + Copy(bullishFVGs, leg.bullishFVGs); + Copy(bearishFVGs, leg.bearishFVGs); + leg.sequentialBullishBars = sequentialsBullishBarsCount; + leg.sequentialBearishBars = sequentialsBearishBarsCount; + + // + result = leg.IsValid(); + } + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + iBar.Clean(); + pBar.Clean(); + zone.Clean(); + iZBar.Clean(); + iZone.Clean(); + jZone.Clean(); + iPattern.Clean(); + XClean(supports); + XClean(patterns); + XClean(bullishBars); + XClean(bearishBars); + XClean(bullishFVGs); + XClean(bearishFVGs); + XClean(resistances); + + // + return result; +} + +bool IsLegPattern1( + XOHCL &bar, + XLeg &leg, + int validationLength = 5, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + leg.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = bar.IsValid() && + fimaParser.IsValid(); + if (!result) + { + return result; + } + + // + int idx = bar.Index(); + while (idx < bar.Index() + loopback) + { + // + } + + // + return result; +} + +////////////////////////////////////////////////// + +// +// Leg ... + +XLeg leg; // Exists Leg ... +bool drawLeg; // Draw Leg ... +bool manageLegs; + +// +bool HasLeg() +{ + return leg.IsValid(); +} + +// +bool ValidateLeg(XOHCL &bar) +{ + // + bool result = false; + + // + result = HasLeg() && + bar.IsValid(); + if (!result) + { + return result; + } + + // + result = + leg.IsBullish() + ? bar.low > leg.lower + : leg.IsBearish() + ? bar.high < leg.upper + : false; + + // + return result; +} + +// +void DrawLeg() +{ + // + if (!drawLeg) + { + return; + } + + // + if (!HasLeg()) + { + return; + } + + // + // Update to Times ... + leg.UpdateTimes(); + + // + // Draw Leg Box ... + XBoxZone legZone; + leg.ToBox(legZone); + if (legZone.IsValid()) + { + // + legZone.to = TimeCurrent(); + poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig); + } + + // + // Draw Legs Other Stufs ... + return; + + // + // FVGs ... + poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig); + + // + // Support and Resistances ... + poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig); + + // + // Patterns ... + poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig); +} + +// +void ManageLeg(XOHCL &bar) +{ + // + // Validate Exists ... + if (HasLeg()) + { + // + if (!ValidateLeg(bar)) + { + // + // Invalidate XLeg ... + leg.Clean(); + } + } + + // + // Detect New ... + if (!HasLeg()) + { + poiDetector.IsLegPattern(bar, leg); + } + + // + // Update Exists ... + if (HasLeg()) + { + // + // Update to Times ... + leg.UpdateTimes(); + + // + DrawLeg(); + } +} + +// +// +// + +ManageLeg(bar); + +// +// Checking For Leg Pattern ... +bool hasLeg = poiDetector.IsLegPattern( + pBar, + _leg, + 3, + 10 // +); +if (hasLeg) +{ + hasLeg = _leg.ToBox(legZone); +} +bool hasBullishLeg = hasLeg && _leg.IsBullish(); +bool hasBearishLeg = hasLeg && _leg.IsBearish(); + +// +// +// + +int CollectPivots( + XPivot &pivots[], + int barIndex = 0, + int loopback = 500 // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + has = false; + XOHCL tmpBar; + XPivot tmpPivot; + double tmpValue; + datetime tmpTime; + bool isBullish = false; + bool isBearish = false; + string tmpSymbol = symbol; + ENUM_TIMEFRAMES tmpPeriod = period; + ENUM_X_DIRECTION tmpDir = X_DIRECTION_NONE; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + tmpBar.Clean(); + tmpPivot.Clean(); + + // + has = tmpBar.Init(tmpSymbol, tmpPeriod, i); + if (!has) + { + continue; + } + + // + // XSAR ... + isBullish = IsSARSwitchedToBullish(i); + isBearish = IsSARSwitchedToBearish(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // XMA Fast / Slow ... + + // + // States ... + isBullish = IsMASlowSwitchedToBullish(i); + isBearish = IsMASlowSwitchedToBearish(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // Crossed Fast Slow ... + isBullish = IsMAFastCrossedOverSlow(i); + isBearish = IsMAFastCrossedUnderSlow(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // Crossed Last ... + isBullish = IsMASlowCrossedOverLast(i); + isBearish = IsMASlowCrossedUnderLast(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // XHK ... + isBullish = IsHKSwitchedToBullish(i); + isBearish = IsHKSwitchedToBearish(i); + has = isBullish || isBearish; + if (has) + { + } + } + + // + result = ArraySize(pivots); + + // + return result; +} + +// +// +// + + +/** + * an strucutre to Model Specified Leg Pattern ... + **/ +struct XLeg +{ + // + // Props ... + + // + datetime time; + string symbol; + ENUM_X_DIRECTION dir; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + XOHCL bullishBars[]; + XOHCL bearishBars[]; + + // + XBoxZone supports[]; + XBoxZone resistances[]; + + // + XBoxZone bullishFVGs[]; + XBoxZone bearishFVGs[]; + + // + XPatternAnalysis patterns[]; + + // + int sequentialBullishBars; + int sequentialBearishBars; + + // + // Constructor ... + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + symbol = NULL; + period = NULL; + dir = X_DIRECTION_NONE; + + // + upper = 0; + lower = 0; + sequentialBullishBars = 0; + sequentialBearishBars = 0; + + // + XClean(patterns); + XClean(supports); + XClean(bullishBars); + XClean(bearishBars); + XClean(resistances); + XClean(bullishFVGs); + XClean(bearishFVGs); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsXValid(time) && + IsXValid(symbol) && + IsXValid(period) && + HasDirection(dir) && + NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + return result; + } + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + return IsValid() && + IsXBullish(dir); + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + return IsValid() && + IsXBearish(dir); + } + + /** + * Converts a Leg to XBoxZone ... + * + * @param zone: XBoxZone, reference to holds Converted ... + * + * @return ( bool ) + */ + bool ToBox(XBoxZone &zone) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + zone.at = time; + zone.dir = dir; + zone.from = time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = symbol; + zone.period = period; + zone.to = TimeCurrent(); + zone.type = ToXString(X_BAR_PATTERN_LEG); + + // + result = zone.IsValid(); + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Update Times of Collections ... + * + * @param value: datetime, Specified Time ... + */ + void UpdateTimes(datetime value = NULL) + { + // + // Normalize ... + value = NormalizeTime(value); + + // + // Validate ... + if (!IsValid()) + { + return; + } + + // + UpdateToTime(supports, value); + UpdateToTime(resistances, value); + UpdateToTime(bullishFVGs, value); + UpdateToTime(bearishFVGs, value); + } + + // +}; diff --git a/BKPS/14041018/Documents/Diagrams/MQL5.X121XKI.Board.kanban b/BKPS/14041018/Documents/Diagrams/MQL5.X121XKI.Board.kanban new file mode 100644 index 0000000..ad0a2bb --- /dev/null +++ b/BKPS/14041018/Documents/Diagrams/MQL5.X121XKI.Board.kanban @@ -0,0 +1,686 @@ +{ + "lists": [ + { + "id": "d66f2925-aa4e-46e4-8f3e-f2c0ba6c9454", + "title": "Backlog", + "cards": [] + }, + { + "id": "61ca33e6-05e4-4b44-b88d-3bc8ae5cba86", + "title": "To Do", + "cards": [] + }, + { + "id": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", + "title": "Doing", + "cards": [ + { + "id": "a59a73f4-1ab4-477b-893e-b2dfb71fe6ea", + "listId": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", + "title": "Add Support for PV in XKI Indicator.", + "description": "", + "labels": [], + "checkboxes": [], + "comments": [] + }, + { + "id": "f8eb6951-f337-40da-9b98-e468f77709fd", + "listId": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", + "title": "implementing Signallers Has Strategy Functions ...", + "description": "Fill Signal Strategies\n", + "labels": [], + "checkboxes": [ + { + "id": "832b1c6e-8219-48ed-a897-45251f444cb1", + "title": "Strategy 1", + "checked": false + }, + { + "id": "ca4683e7-14f0-4dde-86a2-16ea71e08a48", + "title": "Add more Validations on Entries in Strategy 1;", + "checked": false + }, + { + "id": "bd3c09a7-1fbf-45f9-bcf7-ec0f71d1be24", + "title": "adding support Validate by Support and Resistances Zones; on Strategy 1; ", + "checked": false + } + ], + "comments": [] + }, + { + "id": "bad677c0-a119-4f44-be8b-185fc4c996c7", + "listId": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", + "title": "add Targets in strategy 1", + "description": "use Guards Instead of Targets.", + "labels": [], + "checkboxes": [], + "comments": [] + }, + { + "id": "bcb422f9-89db-4816-ba3a-bae95c9c8da4", + "listId": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", + "title": "Test all XKI Helper Functions", + "description": "Test all KI Parser Conditional Tools ...\n ", + "labels": [], + "checkboxes": [ + { + "id": "987aadc7-1775-4ddb-96a8-c7867b41c5dc", + "title": "IsKIFastBullish", + "checked": true + }, + { + "id": "33d30e91-1d65-4cc9-8955-4fcdac1a1a1c", + "title": "IsKIFastBearish", + "checked": true + }, + { + "id": "f5efdef3-3dd5-4a67-9335-27ade4a08119", + "title": "IsKIFastSwitchedToBullish", + "checked": true + }, + { + "id": "95fd5f87-3076-4a10-9d1d-2190c74e77dc", + "title": "IsKIFastSwitchedToBearish", + "checked": true + }, + { + "id": "5848cd3c-7f60-4310-adde-56d0e80896a2", + "title": "IsKIFastOverLast", + "checked": true + }, + { + "id": "879b6657-8a36-4329-9edd-2b5243733c37", + "title": "IsKIFastUnderLast", + "checked": true + }, + { + "id": "7ebd6627-2bd7-47b1-9b3c-51643a446cb3", + "title": "IsKIFastSameAsLast", + "checked": true + }, + { + "id": "4533e930-8c54-45ea-95b8-a95aa9278bd8", + "title": "IsKIFastSwitchedOverLast", + "checked": true + }, + { + "id": "1231584a-5181-457b-8f31-02da2962c54a", + "title": "IsKIFastSwitchedUnderLast", + "checked": true + }, + { + "id": "67f9ccdb-eff3-4e1e-945b-5232773f16f5", + "title": "IsKISlowBullish", + "checked": true + }, + { + "id": "2262f093-f7c9-4a73-983c-055b6098f915", + "title": "IsKISlowBearish", + "checked": true + }, + { + "id": "0e6b67fe-0ff5-4783-a4e3-36b3a70007f5", + "title": "IsKISlowSwitchedToBullish", + "checked": true + }, + { + "id": "0ec4ea00-63bc-4059-92e2-46afa6793325", + "title": "IsKISlowSwitchedToBearish", + "checked": true + }, + { + "id": "cf71aa02-fbf9-4f42-a4f2-791353cc290e", + "title": "IsKISlowOverLast", + "checked": true + }, + { + "id": "da046ac2-0ed5-4c45-ba5b-ffd31a1f65a3", + "title": "IsKISlowUnderLast", + "checked": true + }, + { + "id": "f57c9dde-9294-4909-b5c8-4a8a9a661072", + "title": "IsKISlowSameAsLast", + "checked": true + }, + { + "id": "c52951e5-7a57-4823-a061-9d7a4aa9f0f4", + "title": "IsKISlowSwitchedOverLast", + "checked": true + }, + { + "id": "9e523117-d742-4ffa-ae7d-cbd995b6bc61", + "title": "IsKISlowSwitchedUnderLast", + "checked": true + }, + { + "id": "3ae34a28-6172-4209-832d-41647e45c072", + "title": "IsKISuperSlowBullish", + "checked": true + }, + { + "id": "a7720bdf-2535-430f-9f55-81fa2d281910", + "title": "IsKISuperSlowBearish", + "checked": true + }, + { + "id": "b03e521f-d1b4-4e83-9aaa-6a65297420d5", + "title": "IsKISuperSlowSwitchedToBullish", + "checked": true + }, + { + "id": "3a59a397-816d-4e41-93cd-cab889ebcc1e", + "title": "IsKISuperSlowSwitchedToBearish", + "checked": true + }, + { + "id": "315380e3-702b-41bf-abf5-4b85c0e00ce4", + "title": "IsKISuperSlowOverLast", + "checked": true + }, + { + "id": "3a18f5b6-f18e-43d8-b8e6-43fc530ac80d", + "title": "IsKISuperSlowUnderLast", + "checked": true + }, + { + "id": "4174d12c-382f-4615-9a65-99c447fa6a2a", + "title": "IsKISuperSlowSameAsLast", + "checked": true + }, + { + "id": "03c1fc35-b0c4-477f-ab30-d183a990aff1", + "title": "IsKISuperSlowSwitchedOverLast", + "checked": true + }, + { + "id": "82f549d7-6afa-4408-9d3a-d41d4d623bb7", + "title": "IsKISuperSlowSwitchedUnderLast", + "checked": true + }, + { + "id": "abd7362a-29ba-4f92-9fe0-0496ccb7e9c6", + "title": "IsKIWaveBullish", + "checked": true + }, + { + "id": "440e446f-9aa9-4f74-a950-63a013b42fa5", + "title": "IsKIWaveBearish", + "checked": true + }, + { + "id": "2606bddb-aae1-4cca-8a29-b11c9f7015e6", + "title": "IsKIWaveSwitchedToBullish", + "checked": true + }, + { + "id": "2036fddf-c4eb-4c5d-a550-d3f84341e78b", + "title": "IsKIWaveSwitchedToBearish", + "checked": true + }, + { + "id": "649905b4-d0e9-4009-aeda-08a633861201", + "title": "IsKIWaveOverLast", + "checked": true + }, + { + "id": "cc181a1f-298a-438d-afc8-74b0d4200228", + "title": "IsKIWaveUnderLast", + "checked": true + }, + { + "id": "66bafec6-7794-4650-8919-d6409b49fbdf", + "title": "IsKIWaveSwitchedOverLast", + "checked": true + }, + { + "id": "a5a714cb-ea11-42e3-8e9c-8745405998ae", + "title": "IsKIWaveSwitchedUnderLast", + "checked": true + }, + { + "id": "b94e9071-5f85-4a38-828c-7cf8a1e99a63", + "title": "IsPriceOverKIUpper", + "checked": true + }, + { + "id": "f534622b-5a7f-4c9c-85ed-c562d907fd89", + "title": "IsPriceSwitchedOverKIUpper", + "checked": true + }, + { + "id": "c3a7d88b-c81f-46d4-a3cc-a0d1f5597371", + "title": "IsPriceUnderKIUpper", + "checked": true + }, + { + "id": "8e559cb9-f6a9-412e-8882-e622030cf838", + "title": "IsPriceSwitchedUnderKIUpper", + "checked": true + }, + { + "id": "1efcb06a-0edd-41d0-8e8b-18cba4f64226", + "title": "IsPriceOverKILower", + "checked": true + }, + { + "id": "b16ad1a1-1fb2-4bb6-b2f8-f9310d012f4f", + "title": "IsPriceSwitchedOverKILower", + "checked": true + }, + { + "id": "7e95d7e0-a50f-412b-a024-2568bf66c3f1", + "title": "IsPriceUnderKILower", + "checked": true + }, + { + "id": "dd0deb1f-a259-4ce9-a471-92e268e10abe", + "title": "IsPriceSwitchedUnderKILower", + "checked": true + }, + { + "id": "d747f70e-af68-42f1-a621-efd3ce518b47", + "title": "IsPriceInsideKIBands", + "checked": true + }, + { + "id": "ebf997ee-8944-4442-86fb-6d01ea64b8a6", + "title": "IsMAFastBullish", + "checked": true + }, + { + "id": "e756a5d0-4477-4277-be7d-5897079add6a", + "title": "IsMAFastSwitchedToBullish", + "checked": true + }, + { + "id": "11eb8b4c-004c-4272-921f-4067315aac6a", + "title": "IsMAFastBearish", + "checked": true + }, + { + "id": "548819d7-06fa-4ca5-adf2-c4c2d3064d7e", + "title": "IsMAFastSwitchedToBearish", + "checked": true + }, + { + "id": "90451b0f-ec2e-48e0-8797-7f48cedf743c", + "title": "IsMAFastOverLast", + "checked": true + }, + { + "id": "14210197-c670-4f49-8935-b65926945837", + "title": "IsMAFastSwitchedOverLast", + "checked": true + }, + { + "id": "6158296f-fec3-443e-826b-84a481225013", + "title": "IsMAFastUnderLast", + "checked": true + }, + { + "id": "e84b372e-fbdc-45da-a604-76a0fc6381c4", + "title": "IsMAFastSwitchedUnderLast", + "checked": true + }, + { + "id": "ef0feb55-069c-4e9a-a56e-de05f6b6801f", + "title": "IsMASlowBullish", + "checked": true + }, + { + "id": "0568553a-8ad1-4588-834e-26befe2a9bbb", + "title": "IsMASlowSwitchedToBullish", + "checked": true + }, + { + "id": "630cd36a-f848-44d6-958b-728c4757df6e", + "title": "IsMASlowBearish", + "checked": true + }, + { + "id": "62899e4a-87da-4fc9-8b4b-f1b8b077c177", + "title": "IsMASlowSwitchedToBearish", + "checked": true + }, + { + "id": "acca2b2e-27d6-44dc-bd7f-98857e1b7e64", + "title": "IsMASlowOverLast", + "checked": true + }, + { + "id": "762fd136-113c-444f-8373-2104bc4db466", + "title": "IsMASlowSwitchedOverLast", + "checked": true + }, + { + "id": "49631b5a-8b69-4649-a47d-bef5bda3e137", + "title": "IsMASlowUnderLast", + "checked": true + }, + { + "id": "3cd7c2a1-8a8a-4aba-85c2-6279a356c49e", + "title": "IsMASlowSwitchedUnderLast", + "checked": true + }, + { + "id": "43bbc4df-7601-4460-b636-61b73b30f10a", + "title": "IsMASuperSlowBullish", + "checked": true + }, + { + "id": "a64507e6-c99a-4e6a-a995-c1be671d1083", + "title": "IsMASuperSlowSwitchedToBullish", + "checked": true + }, + { + "id": "91c30277-6ea9-40e8-8467-d06beabf486b", + "title": "IsMASuperSlowBearish", + "checked": true + }, + { + "id": "65295670-87f7-481c-ab9e-a92c8606923f", + "title": "IsMASuperSlowSwitchedToBearish", + "checked": true + }, + { + "id": "0a102b6a-fabe-4aba-938f-d87a22e11b5e", + "title": "IsMASuperSlowOverLast", + "checked": true + }, + { + "id": "cc1a7131-227d-4007-82ed-78c8cc9ef33e", + "title": "IsMASuperSlowSwitchedOverLast", + "checked": true + }, + { + "id": "97e4a349-77c8-4997-8f1b-875fff8229ab", + "title": "IsMASuperSlowUnderLast", + "checked": true + }, + { + "id": "93899467-f06d-420a-ac6e-e645c8c07389", + "title": "IsMASuperSlowSwitchedUnderLast", + "checked": true + }, + { + "id": "2cbc64ba-1882-47a6-9206-7b25e8008395", + "title": "IsMACrossoverBullish", + "checked": true + }, + { + "id": "d7af351b-1de4-4ca9-958a-388d944d4fa9", + "title": "IsMACrossoverSwitchedToBullish", + "checked": true + }, + { + "id": "44b233e6-5a56-4f3a-9c28-60e11aa2059a", + "title": "IsMACrossoverBearish", + "checked": true + }, + { + "id": "5af39475-d1f8-477f-b867-5359aaaf94fa", + "title": "IsMACrossoverSwitchedToBearish", + "checked": true + }, + { + "id": "d2a8183b-3553-4016-8155-a114c70da5ec", + "title": "IsPeakSameAsLast", + "checked": true + }, + { + "id": "7395f77c-7491-417e-8ca8-a41923b46b68", + "title": "IsPeakOverLast", + "checked": true + }, + { + "id": "afdae94d-1a14-408d-b1bd-e84c0868a655", + "title": "IsPeakUnderLast", + "checked": true + }, + { + "id": "45f52be4-1f08-4e7a-b15b-d8db48752449", + "title": "IsValeSameAsLast", + "checked": true + }, + { + "id": "ebc003bc-850d-44e2-a0ed-5ddaba71ae1a", + "title": "IsValeOverLast", + "checked": true + }, + { + "id": "c979f0c3-e356-4fa6-bead-596e4a06b962", + "title": "IsValeUnderLast", + "checked": true + }, + { + "id": "dd69c2c0-c999-4235-8cb5-74607b27c7ec", + "title": "IsATRBreakoutUp", + "checked": false + }, + { + "id": "1a77e8e1-b3e8-48b4-b072-1cda3a69c6f9", + "title": "IsATRBreakoutDown", + "checked": false + }, + { + "id": "bfeb3c24-f0ed-4aed-99af-bec8db026a62", + "title": "IsATROverLast", + "checked": false + }, + { + "id": "62881e04-9b38-49e4-ae9d-e5161c1b0b5c", + "title": "IsATRUnderLast", + "checked": false + }, + { + "id": "33ec5ba0-d31a-4602-ba79-7d3b4d9d7986", + "title": "IsATRSwitchedOverLast", + "checked": false + }, + { + "id": "cf0fb674-8dfc-4ed1-b1dd-5a8447d818a4", + "title": "IsATRSwitchedUnderLast", + "checked": false + }, + { + "id": "ab07c8e5-454c-4c9b-a69d-fa2e8330a2e0", + "title": "IsVolatilityHigh", + "checked": false + }, + { + "id": "031521be-0062-4d07-ade4-ff17782888c7", + "title": "IsVolatilityLow", + "checked": false + }, + { + "id": "49376783-45aa-4a57-a304-3547babf0ccd", + "title": "IsVolatilitySwitchdToHigh", + "checked": false + }, + { + "id": "5803601b-9143-471d-968f-59622d37b70a", + "title": "IsVolatilitySwitchdToLow", + "checked": false + }, + { + "id": "0ab99ddc-75b8-45c7-9140-8cd3dc6921c6", + "title": "IsRSIBullish", + "checked": false + }, + { + "id": "ba39f76c-2257-48fe-94ca-addf2148ee23", + "title": "IsRSIBearish", + "checked": false + }, + { + "id": "91c098b3-56d8-4728-b411-edf7e42d60b0", + "title": "IsRSIOverbought", + "checked": false + }, + { + "id": "7917431d-9bc9-4514-8aea-7fae7c11b0de", + "title": "IsRSIOversold", + "checked": false + }, + { + "id": "83d4b28b-fe6c-411c-a209-c57e3c8251d0", + "title": "IsRSISwitchedToOverSold", + "checked": false + }, + { + "id": "96493d94-9db6-49de-a7f1-e3990b9469b8", + "title": "IsRSISwitchedFromOverSold", + "checked": false + }, + { + "id": "02579268-284f-40f3-93c9-0cb3f70d103a", + "title": "IsRSISwitchedToOverbought", + "checked": false + }, + { + "id": "6c473b2e-1b37-44b2-a08c-ce6217d0c00e", + "title": "IsRSISwitchedFromOverbought", + "checked": false + }, + { + "id": "30177c7a-47df-4d90-8132-0f467ebc071c", + "title": "IsRSISwitchedToBullish", + "checked": false + }, + { + "id": "a3e07f9c-72da-49b4-8101-f742644a2b81", + "title": "IsRSISwitchedToBearish", + "checked": false + } + ], + "comments": [] + } + ] + }, + { + "id": "c6b07a7f-d2e7-4f67-a5a9-0d93cd8bf981", + "title": "Test", + "cards": [ + { + "id": "128af636-5cd8-4311-a565-e822ba380d59", + "listId": "c6b07a7f-d2e7-4f67-a5a9-0d93cd8bf981", + "title": "Add Support for ATR MA in XKI Indicator ...", + "description": "since we have to Calculate Volatility of ATR for Reversal or Breakouts,\nwe Have to Compare ATR by it's Moving Averages ...\n\nhere in this task we need to add support for atr MA ...", + "labels": [], + "checkboxes": [ + { + "id": "f3aabe70-9df5-405d-a737-55e9cc6b2027", + "title": "Add Buffer;", + "checked": true + }, + { + "id": "d6d295c4-b3e9-4946-b305-20df0858db59", + "title": "Calculate;", + "checked": true + }, + { + "id": "d0e3f5b6-56c9-41a6-95c0-71de279bc70c", + "title": "Implement in Conditions;", + "checked": true + }, + { + "id": "4827fc2b-e71d-468c-a069-ec5f17bc6962", + "title": "Implement in Helper;", + "checked": true + }, + { + "id": "3fb4bac7-32c5-43be-b6ac-ccf4a15a117b", + "title": "Use in Parser;", + "checked": true + }, + { + "id": "b98a8eee-1cbf-455b-9e8f-e4d42ba3f327", + "title": "Remove threshold;", + "checked": true + }, + { + "id": "c3636ee3-d577-4728-9b2b-a9237687fd1a", + "title": "Refactor Side Affects;", + "checked": true + } + ], + "comments": [ + { + "id": "128f3338-1b62-4c2c-8ce4-723ed97fd41c", + "comment": "here we are going to test changes ..." + } + ] + }, + { + "id": "1b86f94a-a66e-482c-9172-c9dbb338bb63", + "listId": "c6b07a7f-d2e7-4f67-a5a9-0d93cd8bf981", + "title": "Testing POI(s) for Strategies ...", + "description": "we have some POIs in POI Detectors ...\nin this task we have to test them Works ...", + "labels": [], + "checkboxes": [ + { + "id": "224b6c66-341f-4dda-aa25-6b45ab034a6e", + "title": "Add Support Testing them;", + "checked": true + }, + { + "id": "50caaa08-a3a4-4be5-85d8-4ab41e8dd945", + "title": "Add Support for Safe Entry;", + "checked": true + }, + { + "id": "95ee0eba-4e0d-4a6a-be62-93aa562ab767", + "title": "POI", + "checked": true + }, + { + "id": "aec8ebe5-0d88-4ea7-bfd3-eb1a26af8a55", + "title": "Breakout POI", + "checked": true + }, + { + "id": "6104db5f-95b2-401a-9efd-354b685e7a5f", + "title": "Reversal POI", + "checked": true + }, + { + "id": "05aaad69-af4d-4253-89a7-e46a80cae593", + "title": "Continuation POI", + "checked": true + }, + { + "id": "a7a75d64-00dd-4004-bab2-5040a47b8441", + "title": "Exhaustion POI", + "checked": true + }, + { + "id": "a9c52b07-9a50-4c30-abf9-cd8e3febb6aa", + "title": "TrendExhausted POI", + "checked": true + } + ], + "comments": [ + { + "id": "cbcb5bf5-898d-4f5a-88bc-55007a11244c", + "comment": "all POI(s) noe well tested ...\nand everythings ready for implementing Strategies ..." + } + ] + } + ] + }, + { + "id": "89823cc9-39a6-4d8b-bd5e-b6a14c03b01d", + "title": "Done", + "cards": [] + } + ], + "archive": { + "lists": [], + "cards": [] + }, + "settings": { + "labels": [] + } +} \ No newline at end of file diff --git a/BKPS/14041018/Documents/Diagrams/MQL5.XRRTools.Board.kanban b/BKPS/14041018/Documents/Diagrams/MQL5.XRRTools.Board.kanban new file mode 100644 index 0000000..ed00c88 --- /dev/null +++ b/BKPS/14041018/Documents/Diagrams/MQL5.XRRTools.Board.kanban @@ -0,0 +1,46 @@ +{ + "lists": [ + { + "id": "291ee671-37c7-45eb-bd40-24df3cb445ca", + "title": "BackLog", + "cards": [] + }, + { + "id": "53bb4f6a-34b9-48b8-9391-642c42d222d1", + "title": "ToDO", + "cards": [ + { + "id": "b13fa9ba-5a66-42a6-a5eb-50789a59fad3", + "listId": "53bb4f6a-34b9-48b8-9391-642c42d222d1", + "title": "Apply Fix on XRR Tools", + "description": "Try to Recompile XRR Tools and Check it Works Currently or not;", + "labels": [], + "checkboxes": [], + "comments": [] + } + ] + }, + { + "id": "ca095e9c-39f3-44dd-862c-d6c4af1dffff", + "title": "Doing", + "cards": [] + }, + { + "id": "842e4cfc-aee9-4fa7-9321-cc8ba0d194de", + "title": "Test", + "cards": [] + }, + { + "id": "b99e6c6c-ec5c-4f7c-b937-5bbba1551004", + "title": "Done", + "cards": [] + } + ], + "archive": { + "lists": [], + "cards": [] + }, + "settings": { + "labels": [] + } +} \ No newline at end of file diff --git a/BKPS/14041018/Documents/Diagrams/Position Protection.drawio b/BKPS/14041018/Documents/Diagrams/Position Protection.drawio new file mode 100644 index 0000000..d425cb2 --- /dev/null +++ b/BKPS/14041018/Documents/Diagrams/Position Protection.drawio @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BKPS/14041018/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 b/BKPS/14041018/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 new file mode 100644 index 0000000..ebbdc6a --- /dev/null +++ b/BKPS/14041018/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 ... + + // + XClean(fastBuffer); + XClean(mediumBuffer); + XClean(slowBuffer); + XClean(fastStateBuffer); + XClean(mediumStateBuffer); + XClean(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/14041018/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 b/BKPS/14041018/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 new file mode 100644 index 0000000..f7f1edb --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/BKPS/14041018/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 new file mode 100644 index 0000000..6bfab82 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14041018/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..6771036 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14041018/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..6c5284e --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 b/BKPS/14041018/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 new file mode 100644 index 0000000..720c8d3 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.x3ma.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.x3ma.mq5 new file mode 100644 index 0000000..e535571 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xatr.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xatr.mq5 new file mode 100644 index 0000000..08dbc82 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xca.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xca.mq5 new file mode 100644 index 0000000..7e1ec60 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xcatb.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xcatb.mq5 new file mode 100644 index 0000000..8fb1e13 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xche.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xche.mq5 new file mode 100644 index 0000000..d8ed104 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..286882a --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xczone.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xczone.mq5 new file mode 100644 index 0000000..f6d56a4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xdelta.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xdelta.mq5 new file mode 100644 index 0000000..9cadee6 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xdon.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xdon.mq5 new file mode 100644 index 0000000..49785d4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xhk.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xhk.mq5 new file mode 100644 index 0000000..8e23e94 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xich.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xich.mq5 new file mode 100644 index 0000000..89b3fb8 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xoscs.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xoscs.mq5 new file mode 100644 index 0000000..4c32077 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xstr.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xstr.mq5 new file mode 100644 index 0000000..3a95d4d --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xtb.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xtb.mq5 new file mode 100644 index 0000000..f40cea9 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xvolume.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xvolume.mq5 new file mode 100644 index 0000000..657cb9a --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xvwap.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xvwap.mq5 new file mode 100644 index 0000000..ca2a2c4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xwz.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xwz.mq5 new file mode 100644 index 0000000..626ee8e --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Indicators/x-saherelm.x121.xzg.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xzg.mq5 new file mode 100644 index 0000000..d7cde07 --- /dev/null +++ b/BKPS/14041018/Documents/Indicators/x-saherelm.x121.xzg.mq5 @@ -0,0 +1,757 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121_XZG +// Description: Zogzag Implementation ... +// +// +// 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_XZG Indicator" +#property strict + +// +#define ShortName "X121_XZG" + +// +// DEFINITIONS ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +// How to Calculate Up and Down Price ... +enum ENUM_X_ZG_PRICE_MODE +{ + // + X_ZG_PRICE_HIGH_LOW_MODE = 1, + X_ZG_PRICE_OPEN_CLOSE_MODE = 2, +}; + +// +// INPUT ... + +// +input int depth = 12; // Depth +input int deviation = 5; // Deviation +input int backStep = 3; // Back Step +input ENUM_X_ZG_PRICE_MODE mode = X_ZG_PRICE_HIGH_LOW_MODE; // Mode + +// +// BUFFERS ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 5 +#property indicator_plots 3 + +// +// ZigZag ... + +// +#define mainBufferIndex 0 +#define mainBufferPlotIndex 0 +double mainBuffer[]; + +// +#property indicator_label1 "X121_XZG Main" +#property indicator_type1 DRAW_SECTION +#property indicator_color1 clrYellow +#property indicator_width1 2 + +// +// Highs ... + +// +// ZigZag Pointer or Line Indicator ... +#define arrowBufferIndex 1 +#define arrowBufferPlotIndex 1 +double arrowBuffer[]; + +// +#define arrowColorBufferIndex 2 +double arrowColorBuffer[]; + +// +#property indicator_label2 "X121_XZG PV" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 clrAqua, clrMagenta +#property indicator_width2 1 + +// +#define highsBufferIndex 3 +double highsBuffer[]; + +// +// Lows ... + +// +#define lowsBufferIndex 4 +double lowsBuffer[]; + +// +// VARIABLES ... + +// +int mRecalc = 3; // Number of last extremes for recalculation + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // logTag = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // 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 +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[] // +) +{ + // + double mZGHigh[]; + double mZGLow[]; + if (mode == X_ZG_PRICE_OPEN_CLOSE_MODE) + { + // + ArrayCopy( + mZGHigh, + open + // + ); + + // + ArrayCopy( + mZGLow, + close + // + ); + } + else + { + // + ArrayCopy( + mZGHigh, + high + // + ); + + // + ArrayCopy( + mZGLow, + low + // + ); + } + + // + int zigZagResult = CalcukateZigZag( + prev_calculated, + rates_total, + mZGHigh, + mZGLow + // + ); + + // + if (zigZagResult != rates_total) + { + return zigZagResult; + } + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + depth > 0 && + deviation > 0 && + backStep > 0 + // + ; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Main ... + + // + SetIndexBuffer(mainBufferIndex, mainBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mainBufferPlotIndex, PLOT_SHOW_DATA, true); + PlotIndexSetInteger(mainBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(mainBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Arrow ... + + // + SetIndexBuffer(arrowBufferIndex, arrowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_SHOW_DATA, true); + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_ARROW, 159); + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_ARROW_SHIFT, 0); + PlotIndexSetDouble(arrowBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Arrow Color ... + SetIndexBuffer(arrowColorBufferIndex, arrowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculating Zig Zag ... +int CalcukateZigZag( + const int prev_calculated, + const int rates_total, + double &high[], + double &low[] + // +) +{ + // + if (rates_total < 100) + { + return 0; + } + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + double colorIDX = 0; + double lastZigZagValue = 0; + + // + // Initializing ... + if (prev_calculated == 0) + { + // + ArrayInitialize(mainBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(lowsBuffer, 0); + + // + start = depth; + } + + // + // Already Calculated Before ... + if (prev_calculated > 0) + { + // + i = rates_total - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < mRecalc && i > rates_total - 100) + { + // + res = mainBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < rates_total && !IsStopped(); i++) + { + // + mainBuffer[i] = 0; + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < rates_total && !IsStopped(); shift++) + { + // + // Low ... + val = low[Lowest(low, depth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((low[shift] - val) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + lowsBuffer[shift - back] = 0; + } + } + } + } + + // + if (low[shift] == val) + { + lowsBuffer[shift] = val; + } + else + { + lowsBuffer[shift] = 0; + } + + // + // High ... + val = high[Highest(high, depth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - high[shift]) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + highsBuffer[shift - back] = 0; + } + } + } + } + + // + if (high[shift] == val) + { + highsBuffer[shift] = val; + } + else + { + highsBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < rates_total && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = high[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + mainBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = low[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + mainBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + mainBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + mainBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + mainBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + mainBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + mainBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + mainBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + + // + double iZigZagForColor = lastZigZagValue; + double iZigZag = mainBuffer[shift]; + if (iZigZag == 0 && lastZigZagValue != 0) + { + arrowBuffer[shift] = lastZigZagValue; + } + else if (iZigZag != 0) + { + // + lastZigZagValue = iZigZag; + arrowBuffer[shift] = lastZigZagValue; + } + + // + colorIDX = + lastZigZagValue > iZigZagForColor + ? 0 + : lastZigZagValue < iZigZagForColor + ? 1 + : colorIDX; + arrowColorBuffer[shift] = colorIDX; + } + + // + return rates_total; +} + +// +// TOOLS ... + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} diff --git a/BKPS/14041018/Documents/Indicators/x-saherelm.xfima.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.xfima.mq5 new file mode 100644 index 0000000..d13d3ff --- /dev/null +++ b/BKPS/14041018/Documents/Indicators/x-saherelm.xfima.mq5 @@ -0,0 +1,2404 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XFIMA +// 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 XFIMA Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +#define ShortName "XFIMA" + +// +// 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 fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 int maBandLength = 7; // MA Band Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + +// +// 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 showMABand = true; // Show MA Band +input bool showZigZag = true; // Show ZigZag +input bool showZigZagPV = true; // Show ZigZag PV +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 31 +#property indicator_plots 13 + +// +// 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, clrAquamarine, clrAquamarine, clrAquamarine // clrYellow, clrOrangeRed, clrGray +#property indicator_width1 3 + +// +// 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, clrLightCoral, clrLightCoral, clrLightCoral // clrLime, clrRed, clrGray +#property indicator_width2 3 + +// +// 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 Middle ... + +// +#define fiboMiddleBufferIndex 9 +#define fiboMiddleBufferPlotIndex 6 +double fiboMiddleBuffer[]; + +// +#property indicator_label7 "FIBMID" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_width7 2 + +// +// FIBO Lower ... + +// +#define fiboLowerBufferIndex 10 +#define fiboLowerBufferPlotIndex 7 +double fiboLowerBuffer[]; + +// +#property indicator_label8 "FIBLO" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrMagenta +#property indicator_width8 2 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 11 +#define zigzagBufferPlotIndex 8 +double zigzagBuffer[]; + +// +#property indicator_label9 "XZG" +#property indicator_type9 DRAW_SECTION +#property indicator_color9 clrYellow +#property indicator_width9 2 + +// +// ZG Peak ... + +// +#define zigzagPeakBufferIndex 12 +#define zigzagPeakBufferPlotIndex 9 +double zigzagPeakBuffer[]; + +// +#property indicator_label10 "XZG Peak" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrYellow +#property indicator_width10 3 + +// +// ZG Vale ... + +// +#define zigzagValeBufferIndex 13 +#define zigzagValeBufferPlotIndex 10 +double zigzagValeBuffer[]; + +// +#property indicator_label11 "XZG Peak" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrDarkOrange +#property indicator_width11 3 + +// +// MA Upper Boundary ... + +// +#define maUpperBufferIndex 14 +#define maUpperBufferPlotIndex 11 +double maUpperBuffer[]; + +// +#property indicator_label12 "UpperMA" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrAqua +#property indicator_width12 3 + +// +// MA Lower Boundary ... + +// +#define maLowerBufferIndex 15 +#define maLowerBufferPlotIndex 12 +double maLowerBuffer[]; + +// +#property indicator_label13 "LowerMA" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrMagenta +#property indicator_width13 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 15 + +// +// 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[]; + +// +// ZigZag ... + +// +#define highsBufferIndex mLastBufferIndex + 12 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 13 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 14 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 15 +double lowsTimeBuffer[]; + +// +// 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 maUpperHandler = INVALID_HANDLE; +int maLowerHandler = INVALID_HANDLE; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Requirements ... +CArrayObj mObjects; +XCPOIDrawer *mDrawer; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; +int zigzagRecalc = 3; // Number of last extremes for recalculation + +// +double lastZigZagPeak = 0; +datetime lastZigZagPeakTime = NULL; + +// +double lastZigZagVale = 0; +datetime lastZigZagValeTime = NULL; + +// +// 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); + IndicatorRelease(maUpperHandler); + IndicatorRelease(maLowerHandler); +} + +/** + * 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // Calculating Limit ... + limit = prev_calculated == 0 + ? rates_total - 1 + : rates_total - prev_calculated; + if (limit <= 0) + { + limit = rates_total - 1; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total - 1 && !IsStopped(); i++) + { + // + Print("Calculating Bar Index: ", i); + + // + // Calculate Peaks and Vales ... + CalculateZigZagPV( + i, + prev_calculated, + rates_total // + ); + } + + // + // 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); + int maUpperCalculatedBars = BarsCalculated(maUpperHandler); + int maLowerCalculatedBars = BarsCalculated(maLowerHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + maUpperCalculatedBars >= maxLength && + maLowerCalculatedBars >= 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); + int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maUpperBuffer); + int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maLowerBuffer); + + // + // SAR ... + int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + copiedMAUppers >= limit && + copiedMALowers >= 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 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + 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); + result = MathMax(result, maBandLength); + + // + 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); + + // + // Middle ... + ArraySetAsSeries(fiboMiddleBuffer, true); + SetIndexBuffer(fiboMiddleBufferIndex, fiboMiddleBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboMiddleBufferPlotIndex, 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); + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // ZigZag PV ... + + // + ENUM_DRAW_TYPE zigzagPVDrawType = showZigZagPV ? DRAW_ARROW : DRAW_NONE; + + // + // ZG Peak ... + + // + SetIndexBuffer(zigzagPeakBufferIndex, zigzagPeakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV); + PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType); + + PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagPeakBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // ZG Vale ... + + // + SetIndexBuffer(zigzagValeBufferIndex, zigzagValeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV); + PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType); + + PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagValeBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Band ... + + // + ENUM_DRAW_TYPE maBandDrawType = showMABand ? DRAW_LINE : DRAW_NONE; + + // + // MA Upper Band ... + + // + ArraySetAsSeries(maUpperBuffer, true); + SetIndexBuffer(maUpperBufferIndex, maUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Lower Band ... + + // + ArraySetAsSeries(maLowerBuffer, true); + SetIndexBuffer(maLowerBufferIndex, maLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // 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); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, 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; + + // + 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; + } + + // + // MA Band Upper ... + maUpperHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_HIGH // + ); + result = maUpperHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Band Lower ... + maLowerHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_LOW // + ); + result = maLowerHandler != 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, + fiboUpperZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboMid = GetFibonacciLevel( + iPeak, + iVale, + fiboMiddleZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboLo = GetFibonacciLevel( + iPeak, + iVale, + fiboLowerZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + fiboUpperBuffer[barIndex] = iFiboUp; + fiboMiddleBuffer[barIndex] = iFiboMid; + 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; +} + +/** + * 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 ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = zigzagDepth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < zigzagRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, zigzagDepth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, zigzagDepth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +/** + * Calculate Peaks and Vales ... + * + * @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 CalculateZigZagPV( + int barIndex, + const int prevCalculated, + const int ratesTotal // +) +{ + // + double iZigZagValue = zigzagBuffer[barIndex]; + + // + // Print("Calculate Bar Index: ", barIndex, ", ZG: ", iZigZagValue, ", ", prevCalculated, ", ", ratesTotal); + + // + // Peak ... + double iHighValue = highsBuffer[barIndex]; + double iHighTimeDouble = highsTimeBuffer[barIndex]; + datetime iHighTime = (datetime)((int)iHighTimeDouble); + if (iHighValue != 0 && iHighValue != EMPTY_VALUE && iZigZagValue == iHighValue) + { + // + peakBuffer[barIndex] = iHighValue; + + // + lastZigZagPeak = iHighValue; + lastZigZagPeakTime = iHighTime; + } + else + { + // + double iValue = emptyValue; + if ( + lastZigZagPeak != emptyValue && + lastZigZagPeak != EMPTY_VALUE && + IsSpecifiedValid(lastZigZagPeakTime)) + { + iValue = lastZigZagPeak; + } + + // + peakBuffer[barIndex] = iValue; + } + + // + // Vale ... + double iLowValue = lowsBuffer[barIndex]; + double iLowTimeDouble = lowsTimeBuffer[barIndex]; + datetime iLowTime = (datetime)((int)iLowTimeDouble); + if (iLowValue != 0 && iLowValue != EMPTY_VALUE && iZigZagValue == iLowValue) + { + // + valeBuffer[barIndex] = iLowValue; + + // + lastZigZagVale = iLowValue; + lastZigZagValeTime = iLowTime; + } + else + { + // + double iValue = emptyValue; + if ( + lastZigZagVale != emptyValue && + lastZigZagVale != EMPTY_VALUE && + IsSpecifiedValid(lastZigZagValeTime)) + { + iValue = lastZigZagVale; + } + + // + valeBuffer[barIndex] = iValue; + } + + // + // ChartRedraw(); +} + +// +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(); +} + +// +// +// + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Documents/Indicators/x-saherelm.xzg.mq5 b/BKPS/14041018/Documents/Indicators/x-saherelm.xzg.mq5 new file mode 100644 index 0000000..4d44b62 --- /dev/null +++ b/BKPS/14041018/Documents/Indicators/x-saherelm.xzg.mq5 @@ -0,0 +1,1097 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XZG +// Description: ZigZag Implementation ... +// +// +// 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 XZG Indicator" +#property strict + +// +#define ShortName "XZG" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +// Inputs ... + +// +input group "Calculation"; +input int depth = 12; // Depth +input int deviation = 5; // Deviation +input int backStep = 3; // Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // Low Detect Mode + +// +// Presentation ... +input group "Presentation"; +input bool showPeaks = true; // Show Peaks +input bool showVales = true; // Show Vales +input bool showZigZag = true; // Show ZigZag +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 7 +#property indicator_plots 3 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 0 +#define zigzagBufferPlotIndex 0 +double zigzagBuffer[]; + +// +#property indicator_label1 "XZG" +#property indicator_type1 DRAW_SECTION +#property indicator_color1 clrYellow +#property indicator_width1 2 + +// +// Peaks ... + +// +#define peakBufferIndex 1 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 3 + +// +// Vales ... + +// +#define valeBufferIndex 2 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 2 + +// +#define highsBufferIndex mLastBufferIndex + 1 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 2 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 3 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 4 +double lowsTimeBuffer[]; + +// +// Variables, Properties and etc ... + +// +int mRecalc = 3; // Number of last extremes for recalculation + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + 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(); + + // + // Initial Requirements ... + + // + // 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // 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; + + // + // Main Loop ... + for (int i = 0; i <= limit - 1 && !IsStopped(); i++) + { + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + // { + // // + // // Calculate Peaks and Vales ... + // CalculatePeaksAndVales( + // 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 = + // + // Inputs ... + depth > 0 && + deviation > 0 && + backStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // PEAK ... + + // + ENUM_DRAW_TYPE peaksDrawType = showPeaks ? DRAW_ARROW : DRAW_NONE; + + // + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPeaks); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, peaksDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ENUM_DRAW_TYPE valesDrawType = showVales ? DRAW_ARROW : DRAW_NONE; + + // + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showVales); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, valesDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // Data Buffers ... + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * 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 ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = depth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < mRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, depth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, depth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +/** + * Calculate Peaks and Vales ... + * + * @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 CalculatePeaksAndVales( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iZigZagValue = zigzagBuffer[barIndex]; + + // + // Peak ... + double iHighValue = highsBuffer[barIndex]; + double iHighTimeDouble = highsTimeBuffer[barIndex]; + datetime iHighTime = (datetime)((int)iHighTimeDouble); + if (iHighValue != 0 && iHighValue != EMPTY_VALUE && iZigZagValue == iHighValue) + { + peakBuffer[barIndex] = iHighValue; + } + else + { + // + double iValue = emptyValue; + + // + peakBuffer[barIndex] = iValue; + } + + // + // Vale ... + double iLowValue = lowsBuffer[barIndex]; + double iLowTimeDouble = lowsTimeBuffer[barIndex]; + datetime iLowTime = (datetime)((int)iLowTimeDouble); + if (iLowValue != 0 && iLowValue != EMPTY_VALUE && iZigZagValue == iLowValue) + { + valeBuffer[barIndex] = iLowValue; + } + else + { + // + double iValue = emptyValue; + + // + valeBuffer[barIndex] = iValue; + } +} + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} diff --git a/BKPS/14041018/Documents/JsModules/mqlHelper.js b/BKPS/14041018/Documents/JsModules/mqlHelper.js new file mode 100644 index 0000000..8fe4e41 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/prepareXCATBEA.js b/BKPS/14041018/Documents/JsModules/prepareXCATBEA.js new file mode 100644 index 0000000..797e213 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/x-color.tools.js b/BKPS/14041018/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/x-file.tools.js b/BKPS/14041018/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..2a3535d --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/x-mql-project.tools.js b/BKPS/14041018/Documents/JsModules/x-mql-project.tools.js new file mode 100644 index 0000000..4a507a4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/x-shell.tools.js b/BKPS/14041018/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/x-type-detector.tools.js b/BKPS/14041018/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/JsModules/x-value.tools.js b/BKPS/14041018/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Logs/x.xczones.full.filter.no-range.logs.xlog b/BKPS/14041018/Documents/Logs/x.xczones.full.filter.no-range.logs.xlog new file mode 100644 index 0000000..0fde107 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Notes/ZigZag Linear Regression Result Test.txt b/BKPS/14041018/Documents/Notes/ZigZag Linear Regression Result Test.txt new file mode 100644 index 0000000..2c2b311 --- /dev/null +++ b/BKPS/14041018/Documents/Notes/ZigZag Linear Regression Result Test.txt @@ -0,0 +1,33 @@ +========== +Test: +========== +TO: D'2024.12.31 21:15:00' +From: D'2024.12.26 19:45:00' + +Support: +========= +Minor: 1.0371600000000001 +Major: 1.0343800000000001 + +Resistance: +============ +Minor: 1.0443899999999999 +Major: 1.04582 + +Slope: +============= +Peak: 0.000003537255859231 +Vale: 0.000004208223277701 + +Intercept: +============== +Peak: 1.0404296187948323 +Vale: 1.0385336052465912 + +Values: +==================== +Peak From: 1.0436237608357177 +Peak To: 1.0405074384237354 + +Vale From: 1.0423336308663556 +Vale To: 1.0386261861587007 diff --git a/BKPS/14041018/Documents/Notes/ZigZag Linear Regression Result XFIMA.txt b/BKPS/14041018/Documents/Notes/ZigZag Linear Regression Result XFIMA.txt new file mode 100644 index 0000000..4b6e1a8 --- /dev/null +++ b/BKPS/14041018/Documents/Notes/ZigZag Linear Regression Result XFIMA.txt @@ -0,0 +1,33 @@ +========== +Test: +========== +TO: D'2024.12.31 21:15:00' O +From: D'2024.12.26 18:55:00' X + +Support: +========= +Minor: 1.0371600000000001 O +Major: 1.0343800000000001 O + +Resistance: +============ +Minor: 1.0443899999999999 O +Major: 1.04582 O + +Slope: +============= +Peak: 0.000003194109764736 X +Vale: 0.000004351756566922 X + +Intercept: +============== +Peak: 1.0405539031901065 X +Vale: 1.0383562942289146 X + +Values: +==================== +Peak From: 1.0434701254053103 X +Peak To: 1.0406241736049306 X + +Vale From: 1.0423294479745144 X +Vale To: 1.0384520328733868 X diff --git a/BKPS/14041018/Documents/SaherElm_Logo_Color.ico b/BKPS/14041018/Documents/SaherElm_Logo_Color.ico new file mode 100644 index 0000000..20f5afe Binary files /dev/null and b/BKPS/14041018/Documents/SaherElm_Logo_Color.ico differ diff --git a/BKPS/14041018/Documents/SaherElm_Logo_Color.png b/BKPS/14041018/Documents/SaherElm_Logo_Color.png new file mode 100644 index 0000000..2b8f4ba Binary files /dev/null and b/BKPS/14041018/Documents/SaherElm_Logo_Color.png differ diff --git a/BKPS/14041018/Documents/Temlates/signalling.function.template.mq5 b/BKPS/14041018/Documents/Temlates/signalling.function.template.mq5 new file mode 100644 index 0000000..3cbd45a --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Temlates/temp.pivot.detect.mq5 b/BKPS/14041018/Documents/Temlates/temp.pivot.detect.mq5 new file mode 100644 index 0000000..2104084 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 b/BKPS/14041018/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 new file mode 100644 index 0000000..297e0b0 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Temlates/x-saherelm.x-panel.ea.mq5 b/BKPS/14041018/Documents/Temlates/x-saherelm.x-panel.ea.mq5 new file mode 100644 index 0000000..08417d4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/Temlates/xwz.signal.senario.template.mq5 b/BKPS/14041018/Documents/Temlates/xwz.signal.senario.template.mq5 new file mode 100644 index 0000000..f9f6052 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_DJ30.spot_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_DJ30.spot_M5.x121.log.txt new file mode 100644 index 0000000..b34e4b4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_EURUSDb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_EURUSDb_M5.x121.log.txt new file mode 100644 index 0000000..3090b4e --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_GBPUSDb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_GBPUSDb_M5.x121.log.txt new file mode 100644 index 0000000..da77ff0 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_NZDUSDb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_NZDUSDb_M5.x121.log.txt new file mode 100644 index 0000000..3e7b695 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCADb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCADb_M5.x121.log.txt new file mode 100644 index 0000000..c7124af --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCHFb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDCHFb_M5.x121.log.txt new file mode 100644 index 0000000..d6c7fc6 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDJPYb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_USDJPYb_M5.x121.log.txt new file mode 100644 index 0000000..ad96fe4 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAGUSDb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAGUSDb_M5.x121.log.txt new file mode 100644 index 0000000..10cd061 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAUUSDb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/Pack 1/X121XCATBEA_XAUUSDb_M5.x121.log.txt new file mode 100644 index 0000000..7593994 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt b/BKPS/14041018/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt new file mode 100644 index 0000000..e141480 --- /dev/null +++ b/BKPS/14041018/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/14041018/Documents/XCATBEAInputs/inputs.config.filepath.txt b/BKPS/14041018/Documents/XCATBEAInputs/inputs.config.filepath.txt new file mode 100644 index 0000000..34f0b61 --- /dev/null +++ b/BKPS/14041018/Documents/XCATBEAInputs/inputs.config.filepath.txt @@ -0,0 +1 @@ +X121XCATBEA\X121XCATBEA_XAUUSDb_M5.x121.log diff --git a/BKPS/14041018/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set b/BKPS/14041018/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set new file mode 100644 index 0000000..fff3ec2 Binary files /dev/null and b/BKPS/14041018/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set differ diff --git a/BKPS/14041018/Experts/x-saherelm.backtester.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.backtester.ea.mq5 new file mode 100644 index 0000000..e757bb8 --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.backtester.ea.mq5 @@ -0,0 +1,414 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Experts/x-saherelm.rr.tools.mq5 b/BKPS/14041018/Experts/x-saherelm.rr.tools.mq5 new file mode 100644 index 0000000..c55572a --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.rr.tools.mq5 @@ -0,0 +1,432 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Experts/x-saherelm.x-expert.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.x-expert.ea.mq5 new file mode 100644 index 0000000..4c287aa --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.x-expert.ea.mq5 @@ -0,0 +1,631 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XBaseEA +// Description: Base Expert Advisor as Template ... +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#property description "SaherElm Based Expert Advisor" +#property strict + +// +#define ShortName "XBaseEA" + +// +// Importts ... +#include "../Classes/x-saherelm.x-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 +// [ +// Name| +// 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 +// ) +// ] +// +// +// [XNAME|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 = "[XNAME|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 + +// +// Management Panel ... +input group "Management Panel"; +input bool eaShowPanel = false; // Show Management Panel +double eaPanelAllowedTPSLStep = 10; // Value for Change TP/SL in Each Step +double eaPanelMinAllowedRiskInPoint = 20; // Min Allowed Risk in Point +double eaPanelRiskInPoint = 50; // Risk in Point per Trades +double eaPanelRiskToRewardRatio = 2.0; // Risk To Reward per Trades +double eaPanelVolume = X_MIN_VOLUME; // Default volume Per Trade + +// +// Variables ... + +// +XCBaseExpert *eaExpert; + +// +// Event Handlers ... + +/** + * Initialize EA Process ... + * + * @return ( int ) + */ +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 XCBaseExpert(); + + // + // 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; + + // + // Management Panel ... + eaExpert.eaShowPanel = eaShowPanel; + eaExpert.eaPanelAllowedTPSLStep = eaPanelAllowedTPSLStep; + eaExpert.eaPanelMinAllowedRiskInPoint = eaPanelMinAllowedRiskInPoint; + eaExpert.eaPanelRiskInPoint = eaPanelRiskInPoint; + eaExpert.eaPanelRiskToRewardRatio = eaPanelRiskToRewardRatio; + eaExpert.eaPanelVolume = eaPanelVolume; + + // + // Attach Event Handlers ... + eaExpert.AddOnSignalEventHandler(OnSignalTriggered); + eaExpert.onGuardedEventHandler = OnGuardedTriggered; + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnSignalExecutedEventHandler(OnSignalExecuted); + 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; +} + +/** + * De Initialize Expert ... + * + * @param reason: int, DeInitialization 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 + * + */ +void OnDeinit(const int reason) +{ + // + // Destroy Timer ... + // If Initialized ... + + // + // De Init Expert Class Instance ... + eaExpert.HandleOnDeInit(); + + // + // Cleanup Resources ... + delete eaExpert; + ZeroMemory(eaExpert); +} + +/** + * Handle Tick for Processing ... + */ +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +/** + * Handle On Trade Processing ... + */ +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +/** + * Handle On Timer Processing ... + */ +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +/** + * Handle On Chart Event Processing ... + + * @param id: int, Specified Event ID ... + * @param lparam: long, type event parameter + * @param dparam: double, type event parameter + * @param sparam: string, type event parameter + */ +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 ... + * + * @param guards: XGuard, reference Collection to holds result ... + * @param positions: XPosition, refrence collection to Provides Positions ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( int ) + */ +int CheckForGuardTriggered( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // +) +{ + // + return eaExpert.CheckForGuardTriggered( + guards, + positions, + barIndex // + ); +} + +/** + * 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); +} + +/** + * Trigger OnSignal Executed Event ... + * + * @param signal: XSignal + */ +void OnSignalExecuted(XSignal &signal) +{ + eaExpert.HandleOnSignalExecuted(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(); +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Experts/x-saherelm.x121.xcatb.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.x121.xcatb.ea.mq5 new file mode 100644 index 0000000..4fadd96 --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.x121.xcatb.ea.mq5 @@ -0,0 +1,636 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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 = "XAUUSDb,XAGUSDb,EURUSDb,GBPUSDb,USDCHFb,USDJPYb,USDCADb,NZDUSDb,DowJones30"; // 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/14041018/Experts/x-saherelm.x121.xki.backtester.ea.ex5 b/BKPS/14041018/Experts/x-saherelm.x121.xki.backtester.ea.ex5 new file mode 100644 index 0000000..ffadbf0 Binary files /dev/null and b/BKPS/14041018/Experts/x-saherelm.x121.xki.backtester.ea.ex5 differ diff --git a/BKPS/14041018/Experts/x-saherelm.x121.xki.backtester.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.x121.xki.backtester.ea.mq5 new file mode 100644 index 0000000..d49f7a8 --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.x121.xki.backtester.ea.mq5 @@ -0,0 +1,881 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121XKIEABackTester +// Description: Base Expert Advisor as Template ... +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#property description "SaherElm XFIMA Expert Advisor" +#property strict + +// +#define ShortName "X121XKIEABackTester" + +// +// Importts ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5" + +// #region Inputs ... +// #region Commons ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix +// #endregion + +// #region 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 +// #endregion + +// #region Alert ... +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 +// #endregion + +// #region Configurations ... +input group "Configuration"; +input bool eaProcessAllTicks = false; // Process All Ticks +input double eaSignallerR2R = 2.0; // Risk To Reward Ratio +input double eaSignallerVolume = 0.01; // Default Volume +input double eaSignallerRiskInPoint = 50; // Default Risk In Point +// #endregion + +// #region Bar Time ... +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 +input bool showBars = true; // Show Bars +input bool showBarTime = true; // Show Bar Time +// #endregion + +// #region Indicator Inputs ... +// +input group "Calculation"; +input int kiFastLength = 26; // KI Fast Length +input int kiSlowLength = 104; // KI Slow Length +input int kiSuperSlowLength = 208; // KI Super Slow Length +input int maFastLength = 26; // MA Fast Length +input int maSlowLength = 104; // MA Slow Length +input int maSuperSlowLength = 208; // MA Super Slow Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Mode +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To +input int rsiLength = 14; // RSI Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input int kiWaveSmoothingLength = 14; // RSI KI Wave Smoothing Length +input ENUM_X_MA_METHOD kiWaveSmoothingMode = X_MA_MODE_EMA; // RSI KI Wave Smoothing Method +input double rsiMultiplier = 0.5; // RSI Multiplier +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier +input int atrSmoothingLength = 14; // ATR Smoothing Length +input ENUM_X_MA_METHOD atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Price Type +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Price Type + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showKIFast = true; // Show KI Fast +input bool showKISlow = true; // Show KI Slow +input bool showKISuperSlow = true; // Show KI Super Slow +input bool showMaFast = true; // Show Ma Fast +input bool showMaSlow = true; // Show MA Slow +input bool showMaSuperSlow = true; // Show MA Super Slow +input bool showKIWave = true; // Show KI Wave +input bool showKIUpper = true; // Show KI Upper +input bool showKILower = true; // Show KI Lower + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars +// #endregion +// #endregion + +// #region Local Variables ... +// +// Requirements ... +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Registered Signallers ... +XCX121XKIStrategy1Signaller *signaller1; // XFIMA1 Signaller ... + +// +XBarTracker eaBarTracker; // EA Bar Traker ... + +// +// Registered Handlers ... +int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... +int eaCCHandler = INVALID_HANDLE; // Candle Cleaner Handler ... + +// +bool eaIsNewBar; // Check New Bar ... + +// +ENUM_CHART_MODE eaBarMode = CHART_CANDLES; + +// +color eaBarUpColor = clrLime; +color eaBarDownColor = clrRed; +color eaBarLineColor = clrLime; +color eaBarBearishColor = clrRed; +color eaBarBullishColor = clrLime; +color eaBarVolumesColor = clrGreen; +// #endregion + +// #region 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; + + // + // 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.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnSignalExecutedEventHandler(OnSignalExecuted); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Configure Other Requirements ... + eaExpert.allowedTPSLStep = 10; + eaExpert.minAllowedRiskInPoint = 20; + eaExpert.volume = eaSignallerVolume; + eaExpert.riskToRewardRatio = eaSignallerR2R; + eaExpert.riskInPoint = eaSignallerRiskInPoint; + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Here Instantiate Signaller Class ... + + // + // Preparing Indicator Inputs ... + X121XKIInputs kiInputs; + + // + // This is Default Configuration ... + kiInputs.Default(); + kiInputs.Hide(); + + // + // Here we Attach Inputs to Indicator ... + kiInputs.kiFastLength = kiFastLength; + kiInputs.kiSlowLength = kiSlowLength; + kiInputs.kiSuperSlowLength = kiSuperSlowLength; + kiInputs.maFastLength = maFastLength; + kiInputs.maSlowLength = maSlowLength; + kiInputs.maSuperSlowLength = maSuperSlowLength; + kiInputs.maMethod = maMethod; + kiInputs.maAppliedTo = maAppliedTo; + kiInputs.rsiLength = rsiLength; + kiInputs.rsiAppliedTo = rsiAppliedTo; + kiInputs.kiWaveSmoothingLength = kiWaveSmoothingLength; + kiInputs.kiWaveSmoothingMode = kiWaveSmoothingMode; + kiInputs.rsiMultiplier = rsiMultiplier; + kiInputs.atrLength = atrLength; + kiInputs.atrMultiplier = atrMultiplier; + kiInputs.atrSmoothingLength = atrSmoothingLength; + kiInputs.atrSmoothingMode = atrSmoothingMode; + kiInputs.atrUpperPriceType = atrUpperPriceType; + kiInputs.atrLowerPriceType = atrLowerPriceType; + kiInputs.showPV = showPV; + kiInputs.showKIFast = showKIFast; + kiInputs.showKISlow = showKISlow; + kiInputs.showKISuperSlow = showKISuperSlow; + kiInputs.showMaFast = showMaFast; + kiInputs.showMaSlow = showMaSlow; + kiInputs.showMaSuperSlow = showMaSuperSlow; + kiInputs.showKIWave = showKIWave; + kiInputs.showKIUpper = showKIUpper; + kiInputs.showKILower = showKILower; + kiInputs.startCalculationForLastBars = startCalculationForLastBars; + + // + // Instantiate Signaller ... + + // + // X121XKI1 Signaller ... + signaller1 = new XCX121XKIStrategy1Signaller( + _Symbol, + _Period, + kiInputs, + eaProcessAllTicks, // Process All Ticks ... + eaSignallerR2R, // Signaller Risk to Reward Ratio ... + eaSignallerRiskInPoint, // Default Risk In Points ... + eaSignallerVolume // Defaul Volume ... + ); + + // + // Configure Signaller ... + signaller1.ignoreTargets = false; + signaller1.slAdditionDistance = 30; + signaller1.maxAllowedRiskDistance = 350; + signaller1.AddOnSignalEventHandler(OnSignalTriggered); + + // + isInited = + signaller1.IsValid(); + 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 Candle Cleaner Handler ... + eaCCHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + eaBarMode, // Mode + eaBarUpColor, // Up Color + eaBarDownColor, // Down Color + eaBarLineColor, // Line mode and Doji candlestick Color + eaBarBullishColor, // Bearish Color + eaBarBearishColor, // Bullish Color + eaBarVolumesColor, // Volumes Color + // + // Presentation ... + "", + showBars // Show Candles + // + ); + isInited = eaCCHandler != 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; + } + + // + // Configure XFIMA POI Detector / Drawer ... + // detectorConfig.Default(); + // detectorConfig.FullDetect(); + // marketStructureDrawerConfig.FullDraw(); + + // + // Ignoring Position Drawer ... + delete eaExpert.eaPositionDrawer; + ZeroMemory(eaExpert.eaPositionDrawer); + eaExpert.eaPositionDrawer = NULL; + + // + 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(eaCTHandler); + + // + eaBarTracker.Clean(); + + // + delete signaller1; + ZeroMemory(signaller1); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + eaIsNewBar = eaBarTracker.IsNewBar(); + bool canProcess = eaProcessAllTicks + ? true + : eaIsNewBar; + // + eaExpert.HandleOnTick(); + + // + if (!canProcess) + { + return; + } + + // + // Bar Index ... + int barIndex = 0; + + // + // Signallers Calling OnTick ... + signaller1.OnTick(barIndex); + + // + // Checking For Guard only When has Position ... + XPosition positions[]; + int positionsCount = eaExpert.eaTrader.GetPositions( + positions, + signaller1.symbol, + signaller1.name, + signaller1.period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + if (IsValidSize(positionsCount)) + { + // + XGuard guards[]; + int guardsCount = signaller1.CheckForGuard( + guards, + positions, + barIndex // + ); + if (IsValidSize(guardsCount)) + { + // + // Handling Guards ... + eaExpert.eaGuard.DoGuards(guards); + } + } +} + +// +// 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); +} +// #endregion + +// #region Custom Event Handlers ... +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 && + // + // Indicator Inputs ... + // + // KI ... + kiFastLength >= 5 && + kiSlowLength > kiFastLength && + // + // ATR ... + atrLength >= 5 && + // + // RSI ... + rsiLength >= 5 + // + // + ); + 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(); +} + +/** + * Trigger OnSignal Event ... + * + * @param signal: XSignal + */ +void OnSignalTriggered(XSignal &signal) +{ + // // + // // Draw Signal on Chart ... + // XCSignalObject *iSignalObj; + // bool has = signaller1.poiDrawer.DrawSignal( + // signal, + // iSignalObj, + // 7 // + // ); + + // + eaExpert.HandleOnSignalTriggered(signal); +} + +/** + * Trigger OnSignal Executed Event ... + * + * @param signal: XSignal + */ +void OnSignalExecuted(XSignal &signal) +{ + eaExpert.HandleOnSignalExecuted(signal); +} + +/** + * Check For Guard ... + * + * @param guards: XGuard, reference Collection to holds result ... + * @param positions: XPosition, refrence collection to Provides Positions ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( int ) + */ +int CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // +) +{ + // + int result = signaller1.CheckForGuard( + guards, + positions, + barIndex // + ); + + // + return result; +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + eaExpert.HandleOnStopLossTriggered(deal); + + // + HandleBalanceReport(); + HandleWinTrade(deal.positionId, deal.profit); + HandleLoseTrade(deal.positionId, deal.profit); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + eaExpert.HandleOnTakeProfitTriggered(deal); + + // + HandleBalanceReport(); + HandleWinTrade(deal.positionId, deal.profit); +} + +/** + * 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 // + ); + + // + HandleBalanceReport(); + HandleWinTrade(ticket, position.profit); + HandleLoseTrade(ticket, position.profit); +} + +/** + * 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); +} + +/** + * Test Resting Signals ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + */ +void HandleLoseTrade( + ulong ticket = 0, + double profit = 0 // +) +{ + // + // Check Position Loose ... + bool has = ticket > 0 && + profit < 0; + if (!has) + { + return; + } + + // + // NOTE: Here we Can Add Restrictions on Signaller based on our Requirements ... + // restingSignals: Specified Number of Signals which must to Ignore ... + // restUntil: Specified DateTime to Ignore all Signals before it Expiration ... + // restingDelay: Specified Bars Delay to Ignore all Signals before it passed ... + + // + // Increase Resting Signals of Signallers ... + signaller1.LoseTrade(); +} + +/** + * Handle Win Trade ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + */ +void HandleWinTrade( + ulong ticket = 0, + double profit = 0 // +) +{ + // + bool has = ticket > 0 && + profit > 0; + if (!has) + { + return; + } + + // + signaller1.WinTrade(); +} + +/** + * Handle Balance Report ... + */ +void HandleBalanceReport() +{ + // + string message = eaExpert.eaTrader.mAccount.GetBalanceReportMessage(); + eaExpert.eaAlert.SendAlert(message); +} +// #endregion diff --git a/BKPS/14041018/Experts/x-saherelm.xfima.backtester.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.xfima.backtester.ea.mq5 new file mode 100644 index 0000000..0e09aee --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -0,0 +1,965 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5" + +// +// Definitions ... + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_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 ... +// 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 + +// +// Configurations ... +input group "Configuration"; +input bool eaProcessAllTicks = false; // Process All Ticks +input double eaSignallerR2R = 2.0; // Risk To Reward Ratio +input double eaSignallerVolume = 0.01; // Default Volume +input double eaSignallerRiskInPoint = 50; // Default Risk In Point + +// +// 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 fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Middle Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 int maBandLength = 7; // MA Band Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode +input bool hkIgnoreShadows = true; // HK Remove noises +input int hkSmoothingLength = 21; // HK Smoothing Length +input ENUM_X_MA_METHOD hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method +input int atrLength = 14; // ATR Length +input double atrMultiplier = 1.5; // ATR Band Multiplier +input int atrSmoothingLength = 21; // ATR Smoothing Length +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 atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method + +// +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 = false; // Show PV +input bool showHK = false; // Show HK +input bool showSAR = false; // Show Sar +input bool showBars = true; // Show Bars +input bool showMAFast = false; // Show MA Fast +input bool showMASlow = false; // Show MA Slow +input bool showMABand = false; // Show MA Band +input bool showHKBand = false; // Show HK Band +input bool showATRBand = false; // Show ATR Band +input bool showBarTime = true; // Show Bar Time +input bool showZigZag = false; // Show ZigZag +input bool showCyclesMa = false; // Show Cycles MA +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 ... + +// +// Requirements ... +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Registered Signallers ... +XCXFIMAStrategy1Signaller *fima1Signaller; // XFIMA1 Signaller ... + +// +XBarTracker eaBarTracker; // EA Bar Traker ... + +// +// Registered Handlers ... +int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... +int eaCCHandler = INVALID_HANDLE; // Candle Cleaner Handler ... + +// +bool eaIsNewBar; // Check New Bar ... + +// +ENUM_CHART_MODE eaBarMode = CHART_CANDLES; + +// +color eaBarUpColor = clrLime; +color eaBarDownColor = clrRed; +color eaBarLineColor = clrLime; +color eaBarBearishColor = clrRed; +color eaBarBullishColor = clrLime; +color eaBarVolumesColor = clrGreen; + +// +// 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; + + // + // 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.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnSignalExecutedEventHandler(OnSignalExecuted); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Configure Other Requirements ... + eaExpert.allowedTPSLStep = 10; + eaExpert.minAllowedRiskInPoint = 20; + eaExpert.volume = eaSignallerVolume; + eaExpert.riskToRewardRatio = eaSignallerR2R; + eaExpert.riskInPoint = eaSignallerRiskInPoint; + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Here Instantiate Signaller Class ... + + // + // Preparing Indicator Inputs ... + XFIMAInputs fimaInputs; + + // + // This is Default Configuration ... + fimaInputs.Default(); + fimaInputs.Hide(); + + // + // Here we Attach Inputs to Indicator ... + fimaInputs.scMethod = scMethod; + fimaInputs.scPeriod = scPeriod; + fimaInputs.mcMethod = mcMethod; + fimaInputs.mcPeriod = mcPeriod; + fimaInputs.lcMethod = lcMethod; + fimaInputs.lcPeriod = lcPeriod; + fimaInputs.hcMethod = hcMethod; + fimaInputs.hcPeriod = hcPeriod; + fimaInputs.upperMode = upperMode; + fimaInputs.lowerMode = lowerMode; + fimaInputs.fiboUpperZoneLevel = fiboUpperZoneLevel; + fimaInputs.fiboMiddleZoneLevel = fiboMiddleZoneLevel; + fimaInputs.fiboLowerZoneLevel = fiboLowerZoneLevel; + fimaInputs.sarStep = sarStep; + fimaInputs.sarMax = sarMax; + fimaInputs.maMethod = maMethod; + fimaInputs.maAppliedTo = maAppliedTo; + fimaInputs.maFastLength = maFastLength; + fimaInputs.maSlowLength = maSlowLength; + fimaInputs.maBandLength = maBandLength; + fimaInputs.zigzagDepth = zigzagDepth; + fimaInputs.zigzagDeviation = zigzagDeviation; + fimaInputs.zigzagBackStep = zigzagBackStep; + fimaInputs.zigzagUppersMode = zigzagUppersMode; + fimaInputs.zigzagLowersMode = zigzagLowersMode; + fimaInputs.hkIgnoreShadows = hkIgnoreShadows; + fimaInputs.hkSmoothingLength = hkSmoothingLength; + fimaInputs.hkSmoothingMode = hkSmoothingMode; + fimaInputs.atrLength = atrLength; + fimaInputs.atrMultiplier = atrMultiplier; + fimaInputs.atrSmoothingLength = atrSmoothingLength; + fimaInputs.atrUpperPriceType = atrUpperPriceType; + fimaInputs.atrLowerPriceType = atrLowerPriceType; + fimaInputs.atrSmoothingMode = atrSmoothingMode; + fimaInputs.showPV = showPV; + fimaInputs.showHK = showHK; + fimaInputs.showSAR = showSAR; + fimaInputs.showMAFast = showMAFast; + fimaInputs.showMASlow = showMASlow; + fimaInputs.showMABand = showMABand; + fimaInputs.showHKBand = showHKBand; + fimaInputs.showATRBand = showATRBand; + fimaInputs.showZigZag = showZigZag; + fimaInputs.showCyclesMa = showCyclesMa; + fimaInputs.showFiboZone = showFiboZone; + fimaInputs.startCalculationForLastBars = startCalculationForLastBars; + fimaInputs.sarArrowCode = sarArrowCode; + fimaInputs.peakArrowCode = peakArrowCode; + fimaInputs.valeArrowCode = valeArrowCode; + + // + // Instantiate Signaller ... + + // + // XFIMA1 Signaller ... + fima1Signaller = new XCXFIMAStrategy1Signaller( + _Symbol, + _Period, + fimaInputs, + eaProcessAllTicks, // Process All Ticks ... + eaSignallerR2R, // Signaller Risk to Reward Ratio ... + eaSignallerRiskInPoint, // Default Risk In Points ... + eaSignallerVolume // Defaul Volume ... + ); + + // + // Configure Signaller ... + fima1Signaller.ignoreTargets = false; + fima1Signaller.slAdditionDistance = 30; + fima1Signaller.maxAllowedRiskDistance = 350; + fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); + + // + isInited = + fima1Signaller.IsValid(); + 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 Candle Cleaner Handler ... + eaCCHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + eaBarMode, // Mode + eaBarUpColor, // Up Color + eaBarDownColor, // Down Color + eaBarLineColor, // Line mode and Doji candlestick Color + eaBarBullishColor, // Bearish Color + eaBarBearishColor, // Bullish Color + eaBarVolumesColor, // Volumes Color + // + // Presentation ... + "", + showBars // Show Candles + // + ); + isInited = eaCCHandler != 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; + } + + // + // Configure XFIMA POI Detector / Drawer ... + // detectorConfig.Default(); + // detectorConfig.FullDetect(); + // marketStructureDrawerConfig.FullDraw(); + + // + // Ignoring Position Drawer ... + delete eaExpert.eaPositionDrawer; + ZeroMemory(eaExpert.eaPositionDrawer); + eaExpert.eaPositionDrawer = NULL; + + // + 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(eaCTHandler); + + // + eaBarTracker.Clean(); + + // + delete fima1Signaller; + ZeroMemory(fima1Signaller); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + eaIsNewBar = eaBarTracker.IsNewBar(); + bool canProcess = eaProcessAllTicks + ? true + : eaIsNewBar; + // + eaExpert.HandleOnTick(); + + // + if (!canProcess) + { + return; + } + + // + // Bar Index ... + int barIndex = 0; + + // + // Signallers Calling OnTick ... + fima1Signaller.OnTick(barIndex); + + // + // Checking For Guard only When has Position ... + XPosition positions[]; + int positionsCount = eaExpert.eaTrader.GetPositions( + positions, + fima1Signaller.symbol, + fima1Signaller.name, + fima1Signaller.period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + if (IsValidSize(positionsCount)) + { + // + XGuard guards[]; + int guardsCount = fima1Signaller.CheckForGuard( + guards, + positions, + barIndex // + ); + if (IsValidSize(guardsCount)) + { + // + // Handling Guards ... + eaExpert.eaGuard.DoGuards(guards); + } + } +} + +// +// 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)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ); + 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(); +} + +/** + * Trigger OnSignal Event ... + * + * @param signal: XSignal + */ +void OnSignalTriggered(XSignal &signal) +{ + // // + // // Draw Signal on Chart ... + // XCSignalObject *iSignalObj; + // bool has = fima1Signaller.poiDrawer.DrawSignal( + // signal, + // iSignalObj, + // 7 // + // ); + + // + eaExpert.HandleOnSignalTriggered(signal); +} + +/** + * Trigger OnSignal Executed Event ... + * + * @param signal: XSignal + */ +void OnSignalExecuted(XSignal &signal) +{ + eaExpert.HandleOnSignalExecuted(signal); +} + +/** + * Check For Guard ... + * + * @param guards: XGuard, reference Collection to holds result ... + * @param positions: XPosition, refrence collection to Provides Positions ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( int ) + */ +int CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // +) +{ + // + int result = fima1Signaller.CheckForGuard( + guards, + positions, + barIndex // + ); + + // + return result; +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + eaExpert.HandleOnStopLossTriggered(deal); + + // + HandleBalanceReport(); + HandleWinTrade(deal.positionId, deal.profit); + HandleLoseTrade(deal.positionId, deal.profit); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + eaExpert.HandleOnTakeProfitTriggered(deal); + + // + HandleBalanceReport(); + HandleWinTrade(deal.positionId, deal.profit); +} + +/** + * 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 // + ); + + // + HandleBalanceReport(); + HandleWinTrade(ticket, position.profit); + HandleLoseTrade(ticket, position.profit); +} + +/** + * 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); +} + +/** + * Test Resting Signals ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + */ +void HandleLoseTrade( + ulong ticket = 0, + double profit = 0 // +) +{ + // + // Check Position Loose ... + bool has = ticket > 0 && + profit < 0; + if (!has) + { + return; + } + + // + // NOTE: Here we Can Add Restrictions on Signaller based on our Requirements ... + // restingSignals: Specified Number of Signals which must to Ignore ... + // restUntil: Specified DateTime to Ignore all Signals before it Expiration ... + // restingDelay: Specified Bars Delay to Ignore all Signals before it passed ... + + // + // Increase Resting Signals of Signallers ... + fima1Signaller.LoseTrade(); +} + +/** + * Handle Win Trade ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + */ +void HandleWinTrade( + ulong ticket = 0, + double profit = 0 // +) +{ + // + bool has = ticket > 0 && + profit > 0; + if (!has) + { + return; + } + + // + fima1Signaller.WinTrade(); +} + +/** + * Handle Balance Report ... + */ +void HandleBalanceReport() +{ + // + string message = eaExpert.eaTrader.mAccount.GetBalanceReportMessage(); + eaExpert.eaAlert.SendAlert(message); +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Experts/x-saherelm.xfima.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.xfima.ea.mq5 new file mode 100644 index 0000000..38e1bf2 --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.xfima.ea.mq5 @@ -0,0 +1,636 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XFIMAEA +// Description: Base Expert Advisor as Template ... +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#property description "SaherElm XFIMA Expert Advisor" +#property strict + +// +#define ShortName "XFIMAEA" + +// +// Importts ... +#include "../XFIMAEA/Classes/x-saherelm.xfima.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 +// [ +// Name| +// 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 +// ) +// ] +// +// +// [XFIMA1|EURUSDb|M5||25.0|5|] +// [XFIMA1|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)] +// [XFIMA1|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)] +input string eaSymbolConfiguration = "[XFIMA1|EURUSDb|M15||25.0|5|]"; // 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 + +// +// Management Panel ... +input group "Management Panel"; +input bool eaShowPanel = false; // Show Management Panel +double eaPanelAllowedTPSLStep = 10; // Value for Change TP/SL in Each Step +double eaPanelMinAllowedRiskInPoint = 20; // Min Allowed Risk in Point +double eaPanelRiskInPoint = 50; // Risk in Point per Trades +double eaPanelRiskToRewardRatio = 2.0; // Risk To Reward per Trades +double eaPanelVolume = X_MIN_VOLUME; // Default volume Per Trade + +// +// Variables ... + +// +XCXFIMAExpret *eaExpert; + +// +// Event Handlers ... + +/** + * Initialize EA Process ... + * + * @return ( int ) + */ +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 XCXFIMAExpret(); + + // + // 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; + + // + // Management Panel ... + eaExpert.eaShowPanel = eaShowPanel; + eaExpert.eaPanelAllowedTPSLStep = eaPanelAllowedTPSLStep; + eaExpert.eaPanelMinAllowedRiskInPoint = eaPanelMinAllowedRiskInPoint; + eaExpert.eaPanelRiskInPoint = eaPanelRiskInPoint; + eaExpert.eaPanelRiskToRewardRatio = eaPanelRiskToRewardRatio; + eaExpert.eaPanelVolume = eaPanelVolume; + + // + // 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); + + // + // TODO: Attach other Requirements if necessary ... + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + Print(ShortName, ": Initialized Successfully ..."); + return INIT_SUCCEEDED; +} + +/** + * De Initialize Expert ... + * + * @param reason: int, DeInitialization 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 + * + */ +void OnDeinit(const int reason) +{ + // + // Destroy Timer ... + // If Initialized ... + + // + // De Init Expert Class Instance ... + eaExpert.HandleOnDeInit(); + + // + // Cleanup Resources ... + delete eaExpert; + ZeroMemory(eaExpert); +} + +/** + * Handle Tick for Processing ... + */ +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +/** + * Handle On Trade Processing ... + */ +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +/** + * Handle On Timer Processing ... + */ +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +/** + * Handle On Chart Event Processing ... + + * @param id: int, Specified Event ID ... + * @param lparam: long, type event parameter + * @param dparam: double, type event parameter + * @param sparam: string, type event parameter + */ +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 ... + * + * @param guards: XGuard, reference Collection to holds result ... + * @param positions: XPosition, refrence collection to Provides Positions ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( int ) + */ +int CheckForGuardTriggered( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // +) +{ + // + return eaExpert.CheckForGuardTriggered( + guards, + positions, + barIndex // + ); +} + +/** + * 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); +} + +/** + * Trigger OnSignal Executed Event ... + * + * @param signal: XSignal + */ +void OnSignalExecuted(XSignal &signal) +{ + eaExpert.HandleOnSignalExecuted(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(); +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Experts/x-saherelm.xom1.ea.mq5 b/BKPS/14041018/Experts/x-saherelm.xom1.ea.mq5 new file mode 100644 index 0000000..e4e3f24 --- /dev/null +++ b/BKPS/14041018/Experts/x-saherelm.xom1.ea.mq5 @@ -0,0 +1,571 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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[], + XPosition &positions[], + int barIndex = 0 // +) +{ + 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/14041018/Files/XBackTester_EURUSDb_Ini.dat b/BKPS/14041018/Files/XBackTester_EURUSDb_Ini.dat new file mode 100644 index 0000000..f66ba6f Binary files /dev/null and b/BKPS/14041018/Files/XBackTester_EURUSDb_Ini.dat differ diff --git a/BKPS/14041018/Files/XBaseEA/XLogs.x121.log b/BKPS/14041018/Files/XBaseEA/XLogs.x121.log new file mode 100644 index 0000000..15a02fd Binary files /dev/null and b/BKPS/14041018/Files/XBaseEA/XLogs.x121.log differ diff --git a/BKPS/14041018/Files/XLogs.x121.log b/BKPS/14041018/Files/XLogs.x121.log new file mode 100644 index 0000000..4c41071 Binary files /dev/null and b/BKPS/14041018/Files/XLogs.x121.log differ diff --git a/BKPS/14041018/Files/XRRToolsEA_EURUSDb_Ini.dat b/BKPS/14041018/Files/XRRToolsEA_EURUSDb_Ini.dat new file mode 100644 index 0000000..64c2524 Binary files /dev/null and b/BKPS/14041018/Files/XRRToolsEA_EURUSDb_Ini.dat differ diff --git a/BKPS/14041018/Files/XRRTools_BTCUSD_Ini.dat b/BKPS/14041018/Files/XRRTools_BTCUSD_Ini.dat new file mode 100644 index 0000000..02656e4 Binary files /dev/null and b/BKPS/14041018/Files/XRRTools_BTCUSD_Ini.dat differ diff --git a/BKPS/14041018/Files/XRRTools_EURUSDb_Ini.dat b/BKPS/14041018/Files/XRRTools_EURUSDb_Ini.dat new file mode 100644 index 0000000..dc84416 Binary files /dev/null and b/BKPS/14041018/Files/XRRTools_EURUSDb_Ini.dat differ diff --git a/BKPS/14041018/Files/XRRTools_USDCADb_Ini.dat b/BKPS/14041018/Files/XRRTools_USDCADb_Ini.dat new file mode 100644 index 0000000..342ee8c Binary files /dev/null and b/BKPS/14041018/Files/XRRTools_USDCADb_Ini.dat differ diff --git a/BKPS/14041018/Files/XRRTools_XAUUSDb_Ini.dat b/BKPS/14041018/Files/XRRTools_XAUUSDb_Ini.dat new file mode 100644 index 0000000..d52c305 Binary files /dev/null and b/BKPS/14041018/Files/XRRTools_XAUUSDb_Ini.dat differ diff --git a/BKPS/14041018/Files/_EURUSDb_Ini.dat b/BKPS/14041018/Files/_EURUSDb_Ini.dat new file mode 100644 index 0000000..5516e8f Binary files /dev/null and b/BKPS/14041018/Files/_EURUSDb_Ini.dat differ diff --git a/BKPS/14041018/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/BKPS/14041018/Helpers/x-saherelm.x121.xcatb.helper.mq5 new file mode 100644 index 0000000..c0b833b --- /dev/null +++ b/BKPS/14041018/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/14041018/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14041018/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..6771036 --- /dev/null +++ b/BKPS/14041018/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/14041018/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14041018/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..6c5284e --- /dev/null +++ b/BKPS/14041018/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/14041018/Helpers/x-saherelm.x121.xki.helper.mq5 b/BKPS/14041018/Helpers/x-saherelm.x121.xki.helper.mq5 new file mode 100644 index 0000000..7f2b11d --- /dev/null +++ b/BKPS/14041018/Helpers/x-saherelm.x121.xki.helper.mq5 @@ -0,0 +1,1629 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XKIHelper +// 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" + +// #region Definitions ... +enum ENUM_X121_XKI_BUFFER_NAME +{ + X121_XKI_NONE = 0, + X121_XKI_FAST = 1, + X121_XKI_SLOW = 2, + X121_XKI_SUPER_SLOW = 3, + X121_XKI_UPPER = 4, + X121_XKI_LOWER = 5, + X121_XKI_WAVE = 6, + X121_XKI_MA_FAST = 7, + X121_XKI_MA_SLOW = 8, + X121_XKI_MA_SUPER_SLOW = 9, + X121_XKI_MA_CROSS = 10, + X121_XKI_ATR = 11, +}; + +bool IsXValid(ENUM_X121_XKI_BUFFER_NAME value) +{ + return value != X121_XKI_NONE; +} +string ToXString(ENUM_X121_XKI_BUFFER_NAME value) +{ + // + string result = NULL; + + // + if (IsXValid(value)) + { + // + switch (value) + { + // + case X121_XKI_FAST: + result = "FAST"; + break; + + // + case X121_XKI_SLOW: + result = "SLOW"; + break; + + // + case X121_XKI_SUPER_SLOW: + result = "SUPER_SLOW"; + break; + + // + case X121_XKI_UPPER: + result = "UPPER"; + break; + + // + case X121_XKI_LOWER: + result = "LOWER"; + break; + + // + case X121_XKI_WAVE: + result = "WAVE"; + break; + + // + case X121_XKI_MA_FAST: + result = "MA_FAST"; + break; + + // + case X121_XKI_MA_SLOW: + result = "MA_SLOW"; + break; + + // + case X121_XKI_MA_SUPER_SLOW: + result = "MA_SUPER_SLOW"; + break; + } + } + + // + return result; +} +ENUM_X121_XKI_BUFFER_NAME ToXKIBufferName(string value) +{ + // + ENUM_X121_XKI_BUFFER_NAME result = X121_XKI_NONE; + + // + if (IsXValid(value)) + { + // + if (value == ToXString(X121_XKI_FAST)) + { + result = X121_XKI_FAST; + } + else if (value == ToXString(X121_XKI_SLOW)) + { + result = X121_XKI_SLOW; + } + else if (value == ToXString(X121_XKI_SUPER_SLOW)) + { + result = X121_XKI_SUPER_SLOW; + } + else if (value == ToXString(X121_XKI_UPPER)) + { + result = X121_XKI_UPPER; + } + else if (value == ToXString(X121_XKI_LOWER)) + { + result = X121_XKI_LOWER; + } + else if (value == ToXString(X121_XKI_WAVE)) + { + result = X121_XKI_WAVE; + } + else if (value == ToXString(X121_XKI_MA_FAST)) + { + result = X121_XKI_MA_FAST; + } + else if (value == ToXString(X121_XKI_MA_SLOW)) + { + result = X121_XKI_MA_SLOW; + } + else if (value == ToXString(X121_XKI_MA_SUPER_SLOW)) + { + result = X121_XKI_MA_SUPER_SLOW; + } + } + + // + return result; +} +// #endregion + +// #region Buffers ... +enum ENUM_X121_XKI_BUFFERS +{ + // + // KI Fast ... + X121_XKI_KI_FAST_LINE = 0, + X121_XKI_KI_FAST_COLOR_LINE = 1, + X121_XKI_KI_FAST_STATE_LINE = 15, + // + // KI Slow ... + X121_XKI_KI_SLOW_LINE = 8, + X121_XKI_KI_SLOW_COLOR_LINE = 9, + X121_XKI_KI_SLOW_STATE_LINE = 22, + // + // KI Super Slow ... + X121_XKI_KI_SUPER_SLOW_LINE = 10, + X121_XKI_KI_SUPER_SLOW_COLOR_LINE = 11, + X121_XKI_KI_SUPER_SLOW_STATE_LINE = 24, + // + // KI Wave ... + X121_XKI_KI_WAVE_LINE = 2, + X121_XKI_KI_WAVE_RAW_LINE = 20, + X121_XKI_KI_WAVE_COLOR_LINE = 3, + X121_XKI_KI_WAVE_STATE_LINE = 21, + // + // Upper/Lower ... + X121_XKI_KI_UPPER_LINE = 4, + X121_XKI_KI_LOWER_LINE = 5, + // + // MA Fast/Slow ... + X121_XKI_MA_FAST_LINE = 6, + X121_XKI_MA_SLOW_LINE = 7, + X121_XKI_MA_SUPER_SLOW_LINE = 12, + // + // PV ... + X121_XKI_PEAK_LINE = 13, + X121_XKI_VALE_LINE = 14, + // + // ATR ... + X121_XKI_ATR_LINE = 16, + X121_XKI_ATR_SMOOTHED_LINE = 23, + X121_XKI_ATR_RAW_UPPER_LINE = 17, + X121_XKI_ATR_RAW_LOWER_LINE = 18, + // + // RSI ... + X121_XKI_RSI_LINE = 19, +}; +// #endregion + +// #region Inputs ... +struct X121XKIInputs +{ + // #region Props ... + // #region Calculations ... + int kiFastLength; // KI Fast Length + int kiSlowLength; // KI Slow Length + int kiSuperSlowLength; // KI Super Slow Length + int maFastLength; // MA Fast Length + int maSlowLength; // MA Slow Length + int maSuperSlowLength; // MA Super Slow Length + ENUM_MA_METHOD maMethod; // MA Mode + ENUM_APPLIED_PRICE maAppliedTo; // MA Applied To + int rsiLength; // RSI Length + ENUM_APPLIED_PRICE rsiAppliedTo; // RSI Applied To + double rsiBullishConfirmation; // RSI Bullish Confirmation Level + double rsiBearishConfirmation; // RSI Bearish Confirmation Level + int kiWaveSmoothingLength; // RSI KI Wave Smoothing Length + ENUM_X_MA_METHOD kiWaveSmoothingMode; // RSI KI Wave Smoothing Method + double rsiMultiplier; // RSI Multiplier + int atrLength; // ATR Length + double atrMultiplier; // ATR Multiplier + int atrSmoothingLength; // ATR Smoothing Length + ENUM_X_MA_METHOD atrSmoothingMode; // ATR Smoothing Method + ENUM_X_PRICE atrUpperPriceType; // ATR Upper Price Type + ENUM_X_PRICE atrLowerPriceType; // ATR Lower Price Type + // #endregion + + // #region Presentations ... + bool showPV; // Show PV + bool showKIFast; // Show KI + bool showKISlow; // Show KI Slow + bool showKISuperSlow; // Show KI Super Slow + bool showMaFast; // Show Ma Fast + bool showMaSlow; // Show MA Slow + bool showMaSuperSlow; // Show MA Super Slow + bool showKIWave; // Show KI Wave + bool showKIUpper; // Show KI Upper + bool showKILower; // Show KI Lower + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + int peakArrowCode; // Peaks Arrow Code + int valeArrowCode; // Vales Arrow Code + // #endregion + // #endregion + + // + // Constructor(s) ... + X121XKIInputs() + { + Clean(); + } + + // #region Tools ... + // + // Clean ... + void Clean() + { + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Calculations ... + kiFastLength = 26; + kiSlowLength = 104; + kiSuperSlowLength = 208; + maFastLength = 26; + maSlowLength = 104; + maSuperSlowLength = 208; + maMethod = MODE_EMA; + maAppliedTo = PRICE_CLOSE; + rsiLength = 14; + rsiAppliedTo = PRICE_CLOSE; + rsiBullishConfirmation = 55; + rsiBearishConfirmation = 45; + kiWaveSmoothingLength = 14; + kiWaveSmoothingMode = X_MA_MODE_EMA; + rsiMultiplier = 0.5; + atrLength = 14; + atrMultiplier = 2; + atrSmoothingLength = 14; + atrSmoothingMode = X_MA_MODE_EMA; + atrUpperPriceType = X_PRICE_HIGH; + atrLowerPriceType = X_PRICE_LOW; + + // + // Presentations ... + showPV = true; + showKIFast = true; + showKISlow = true; + showKISuperSlow = true; + showMaFast = true; + showMaSlow = true; + showMaSuperSlow = true; + showKIWave = true; + showKIUpper = true; + showKILower = true; + + // + startCalculationForLastBars = 1500; + + // + peakArrowCode = 159; + valeArrowCode = 159; + } + + // + // Hide ... + void Hide() + { + // + // Presentations ... + showPV = false; + showKIFast = false; + showKISlow = false; + showKISuperSlow = false; + showMaFast = false; + showMaSlow = false; + showMaSuperSlow = false; + showKIWave = false; + showKIUpper = false; + showKILower = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // KI ... + kiFastLength >= 5 && + kiSlowLength > kiFastLength && + kiSuperSlowLength > kiSlowLength && + // + // MA ... + maFastLength >= 2 && + maSlowLength > maFastLength && + maSuperSlowLength > maSlowLength && + // + // ATR ... + atrLength >= 5 && + // + // RSI ... + rsiLength >= 5 && + rsiBullishConfirmation > 0 && + rsiBullishConfirmation < 100 && + rsiBearishConfirmation > 0 && + rsiBearishConfirmation < 100 + // + ; + + // + return result; + } + // #endregion +}; +// #endregion + +// #region Conditions ... +struct X121XKIConditions +{ + // #region Commons ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + // #endregion + + // #region Buffers ... + double kiFastBuffer[]; + double kiFastColorBuffer[]; + double kiFastStateBuffer[]; + double kiSlowBuffer[]; + double kiSlowColorBuffer[]; + double kiSlowStateBuffer[]; + double kiSuperSlowBuffer[]; + double kiSuperSlowColorBuffer[]; + double kiSuperSlowStateBuffer[]; + double kiWaveBuffer[]; + double kiWaveColorBuffer[]; + double kiUpperBuffer[]; + double kiLowerBuffer[]; + double maFastBuffer[]; + double maSlowBuffer[]; + double maSuperSlowBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double atrBuffer[]; + double atrSmoothedBuffer[]; + double atrRawUpperBuffer[]; + double atrRawLowerBuffer[]; + double rsiBuffer[]; + double kiWaveRawBuffer[]; + double kiWaveStateBuffer[]; + // #endregion + + // + // Constructor ... + X121XKIConditions() + { + Clean(); + } + + // #region Tools ... + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + XClean(kiFastBuffer); + XClean(kiFastColorBuffer); + XClean(kiFastStateBuffer); + XClean(kiSlowBuffer); + XClean(kiSlowColorBuffer); + XClean(kiSlowStateBuffer); + XClean(kiSuperSlowBuffer); + XClean(kiSuperSlowColorBuffer); + XClean(kiSuperSlowStateBuffer); + XClean(kiWaveBuffer); + XClean(kiWaveColorBuffer); + XClean(kiUpperBuffer); + XClean(kiLowerBuffer); + XClean(maFastBuffer); + XClean(maSlowBuffer); + XClean(maSuperSlowBuffer); + XClean(peakBuffer); + XClean(valeBuffer); + XClean(atrBuffer); + XClean(atrSmoothedBuffer); + XClean(atrRawUpperBuffer); + XClean(atrRawLowerBuffer); + XClean(rsiBuffer); + XClean(kiWaveRawBuffer); + XClean(kiWaveStateBuffer); + + // + ArraySetAsSeries(kiFastBuffer, true); + ArraySetAsSeries(kiFastColorBuffer, true); + ArraySetAsSeries(kiFastStateBuffer, true); + ArraySetAsSeries(kiSlowBuffer, true); + ArraySetAsSeries(kiSlowColorBuffer, true); + ArraySetAsSeries(kiSlowStateBuffer, true); + ArraySetAsSeries(kiSuperSlowBuffer, true); + ArraySetAsSeries(kiSuperSlowColorBuffer, true); + ArraySetAsSeries(kiSuperSlowStateBuffer, true); + ArraySetAsSeries(kiWaveBuffer, true); + ArraySetAsSeries(kiWaveColorBuffer, true); + ArraySetAsSeries(kiUpperBuffer, true); + ArraySetAsSeries(kiLowerBuffer, true); + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSuperSlowBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(atrSmoothedBuffer, true); + ArraySetAsSeries(atrRawUpperBuffer, true); + ArraySetAsSeries(atrRawLowerBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(kiWaveRawBuffer, true); + ArraySetAsSeries(kiWaveStateBuffer, true); + + // + ZeroMemory(this); + } + + /** + * Retrieve Unique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetToken(this); + } + // #endregion +}; +// #endregion + +// #region Class ... +class XCX121XKIHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Constructors ... + XCX121XKIHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XKIHelper() + { + } + + // #region Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XKIInputs &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.xki", + "", // Calculation ... + mInputs.kiFastLength, + mInputs.kiSlowLength, + mInputs.kiSuperSlowLength, + mInputs.maFastLength, + mInputs.maSlowLength, + mInputs.maSuperSlowLength, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.rsiLength, + mInputs.rsiAppliedTo, + mInputs.rsiBullishConfirmation, + mInputs.rsiBearishConfirmation, + mInputs.kiWaveSmoothingLength, + mInputs.kiWaveSmoothingMode, + mInputs.rsiMultiplier, + mInputs.atrLength, + mInputs.atrMultiplier, + mInputs.atrSmoothingLength, + mInputs.atrSmoothingMode, + mInputs.atrUpperPriceType, + mInputs.atrLowerPriceType, + "", // Presentation ... + mInputs.showPV, + mInputs.showKIFast, + mInputs.showKISlow, + mInputs.showKISuperSlow, + mInputs.showMaFast, + mInputs.showMaSlow, + mInputs.showMaSuperSlow, + mInputs.showKIWave, + mInputs.showKIUpper, + mInputs.showKILower, + mInputs.startCalculationForLastBars, + mInputs.peakArrowCode, + mInputs.valeArrowCode // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XKIInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XKIInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs // + ); + } + + // + bool GetConditions( + X121XKIConditions &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; + } + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // #region Reading Buffers ... + CopyKIFast( + zIndex, + loopback, + conditions.kiFastBuffer // + ); + CopyKIFastColor( + zIndex, + loopback, + conditions.kiFastColorBuffer // + ); + CopyKIFastState( + zIndex, + loopback, + conditions.kiFastStateBuffer // + ); + CopyKISlow( + zIndex, + loopback, + conditions.kiSlowBuffer // + ); + CopyKISlowColor( + zIndex, + loopback, + conditions.kiSlowColorBuffer // + ); + CopyKISlowState( + zIndex, + loopback, + conditions.kiSlowStateBuffer // + ); + CopyKISuperSlow( + zIndex, + loopback, + conditions.kiSuperSlowBuffer // + ); + CopyKISuperSlowColor( + zIndex, + loopback, + conditions.kiSuperSlowColorBuffer // + ); + CopyKISuperSlowState( + zIndex, + loopback, + conditions.kiSuperSlowStateBuffer // + ); + CopyKIWave( + zIndex, + loopback, + conditions.kiWaveBuffer // + ); + CopyKIWaveRaw( + zIndex, + loopback, + conditions.kiWaveRawBuffer // + ); + CopyKIWaveColor( + zIndex, + loopback, + conditions.kiWaveColorBuffer // + ); + CopyKIWaveState( + zIndex, + loopback, + conditions.kiWaveStateBuffer // + ); + CopyKIUpper( + zIndex, + loopback, + conditions.kiUpperBuffer // + ); + CopyKILower( + zIndex, + loopback, + conditions.kiLowerBuffer // + ); + CopyMAFast( + zIndex, + loopback, + conditions.maFastBuffer // + ); + CopyMASlow( + zIndex, + loopback, + conditions.maSlowBuffer // + ); + CopyMASuperSlow( + zIndex, + loopback, + conditions.maSuperSlowBuffer // + ); + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + CopyATRSmoothed( + zIndex, + loopback, + conditions.atrSmoothedBuffer // + ); + CopyATRRawUpper( + zIndex, + loopback, + conditions.atrRawUpperBuffer // + ); + CopyATRRawLower( + zIndex, + loopback, + conditions.atrRawLowerBuffer // + ); + // #endregion + + // + return result; + } + // #endregion + + // #region Buffer Readers ... + // #region KI Fast ... + // + double GetKIFast( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_FAST_LINE, + barIndex // + ); + } + + // + int CopyKIFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_FAST_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Fast Color ... + // + double GetKIFastColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_FAST_COLOR_LINE, + barIndex // + ); + } + + // + int CopyKIFastColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_FAST_COLOR_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Fast State ... + // + double GetKIFastState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_FAST_STATE_LINE, + barIndex // + ); + } + + // + int CopyKIFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_FAST_STATE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Slow ... + // + double GetKISlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SLOW_LINE, + barIndex // + ); + } + + // + int CopyKISlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SLOW_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Slow Color ... + // + double GetKISlowColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SLOW_COLOR_LINE, + barIndex // + ); + } + + // + int CopyKISlowColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SLOW_COLOR_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Slow State ... + // + double GetKISlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyKISlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SLOW_STATE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Super Slow ... + // + double GetKISuperSlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SUPER_SLOW_LINE, + barIndex // + ); + } + + // + int CopyKISuperSlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SUPER_SLOW_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Super Slow Color ... + // + double GetKISuperSlowColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SUPER_SLOW_COLOR_LINE, + barIndex // + ); + } + + // + int CopyKISuperSlowColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SUPER_SLOW_COLOR_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Super Slow State ... + // + double GetKISuperSlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SUPER_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyKISuperSlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SUPER_SLOW_STATE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Wave ... + // + double GetKIWave( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_WAVE_LINE, + barIndex // + ); + } + + // + int CopyKIWave( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_WAVE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Wave Raw ... + // + double GetKIWaveRaw( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_WAVE_RAW_LINE, + barIndex // + ); + } + + // + int CopyKIWaveRaw( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_WAVE_RAW_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Wave Color ... + // + double GetKIWaveColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_WAVE_COLOR_LINE, + barIndex // + ); + } + + // + int CopyKIWaveColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_WAVE_COLOR_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Wave State ... + // + double GetKIWaveState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_WAVE_STATE_LINE, + barIndex // + ); + } + + // + int CopyKIWaveState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_WAVE_STATE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Upper ... + // + double GetKIUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_UPPER_LINE, + barIndex // + ); + } + + // + int CopyKIUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_UPPER_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Lower ... + // + double GetKILower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_LOWER_LINE, + barIndex // + ); + } + + // + int CopyKILower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_LOWER_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region MA Fast ... + // + double GetMAFast( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_MA_FAST_LINE, + barIndex // + ); + } + + // + int CopyMAFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_MA_FAST_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region MA Slow ... + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_MA_SLOW_LINE, + barIndex // + ); + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_MA_SLOW_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region MA Super Slow ... + // + double GetMASuperSlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_MA_SUPER_SLOW_LINE, + barIndex // + ); + } + + // + int CopyMASuperSlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_MA_SUPER_SLOW_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region Peak ... + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_PEAK_LINE, + barIndex // + ); + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_PEAK_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region Vale ... + // + double GetVale( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_VALE_LINE, + barIndex // + ); + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_VALE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region RSI ... + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_RSI_LINE, + barIndex // + ); + } + + // + int CopyRSI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_RSI_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region ATR ... + // + double GetATR( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_ATR_LINE, + barIndex // + ); + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_ATR_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region ATRSmoothed ... + // + double GetATRSmoothed( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_ATR_SMOOTHED_LINE, + barIndex // + ); + } + + // + int CopyATRSmoothed( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_ATR_SMOOTHED_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region ATR Raw Upper... + // + double GetATRRawUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_ATR_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRRawUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_ATR_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region ATR Raw Lower... + // + double GetATRRawLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_ATR_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRRawLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_ATR_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + // #endregion + // #endregion + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XKIInputs mInputs; // Inputs ... +}; +// #endregion \ No newline at end of file diff --git a/BKPS/14041018/Helpers/x-saherelm.xfima.helper.mq5 b/BKPS/14041018/Helpers/x-saherelm.xfima.helper.mq5 new file mode 100644 index 0000000..5e04adb --- /dev/null +++ b/BKPS/14041018/Helpers/x-saherelm.xfima.helper.mq5 @@ -0,0 +1,2992 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXFIMAHelper +// 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 "../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_XFIMA_BUFFERS +{ + // + // Plot Buffers ... + XFIMA_MA_FAST_LINE = 0, + XFIMA_MA_FAST_COLOR_LINE = 1, + XFIMA_MA_SLOW_LINE = 2, + XFIMA_MA_SLOW_COLOR_LINE = 3, + XFIMA_SAR_LINE = 4, + XFIMA_SAR_COLOR_LINE = 5, + XFIMA_PEAK_LINE = 6, + XFIMA_VALE_LINE = 7, + XFIMA_FIBO_UPPER_LINE = 8, + XFIMA_FIBO_MIDDLE_LINE = 9, + XFIMA_FIBO_LOWER_LINE = 10, + XFIMA_ZIGZAG_LINE = 11, + XFIMA_MA_BAND_UPPER_LINE = 12, + XFIMA_MA_BAND_LOWER_LINE = 13, + XFIMA_HK_OPEN_LINE = 14, + XFIMA_HK_HIGH_LINE = 15, + XFIMA_HK_LOW_LINE = 16, + XFIMA_HK_CLOSE_LINE = 17, + XFIMA_HK_COLOR_LINE = 18, + XFIMA_HK_BAND_UPPER_LINE = 19, + XFIMA_HK_BAND_LOWER_LINE = 20, + XFIMA_PB_BAND_UPPER_LINE = 21, + XFIMA_PB_BAND_LOWER_LINE = 22, + XFIMA_ATR_BAND_UPPER_LINE = 23, + XFIMA_ATR_BAND_LOWER_LINE = 24, + XFIMA_SC_MA_LINE = 25, + XFIMA_MC_MA_LINE = 26, + XFIMA_LC_MA_LINE = 27, + XFIMA_HC_MA_LINE = 28, + // + // Data Buffers ... + XFIMA_MA_FAST_STATE_LINE = 29, + XFIMA_MA_SLOW_STATE_LINE = 30, + XFIMA_SAR_STATE_LINE = 31, + XFIMA_SC_HH_LINE = 32, + XFIMA_SC_LL_LINE = 33, + XFIMA_MC_HH_LINE = 34, + XFIMA_MC_LL_LINE = 35, + XFIMA_LC_HH_LINE = 36, + XFIMA_LC_LL_LINE = 37, + XFIMA_HC_HH_LINE = 38, + XFIMA_HC_LL_LINE = 39, + XFIMA_ZIGZAG_HIGHS_LINE = 40, + XFIMA_ZIGZAG_HIGHS_TIME_LINE = 41, + XFIMA_ZIGZAG_LOWS_LINE = 42, + XFIMA_ZIGZAG_LOWS_TIME_LINE = 43, + XFIMA_HK_RAW_OPEN_LINE = 44, + XFIMA_HK_RAW_HIGH_LINE = 45, + XFIMA_HK_RAW_LOW_LINE = 46, + XFIMA_HK_RAW_CLOSE_LINE = 47, + XFIMA_PB_BAND_RAW_UPPER_LINE = 48, + XFIMA_PB_BAND_RAW_LOWER_LINE = 49, + XFIMA_ATR_LINE = 50, + XFIMA_ATR_BAND_RAW_UPPER_LINE = 51, + XFIMA_ATR_BAND_RAW_LOWER_LINE = 52, + XFIMA_SC_MA_STATE_LINE = 53, + XFIMA_MC_MA_STATE_LINE = 54, + XFIMA_LC_MA_STATE_LINE = 55, + XFIMA_HC_MA_STATE_LINE = 56, +}; + +// +// Input Models ... +struct XFIMAInputs +{ + // + // 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 fiboUpperZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboLowerZoneLevel; // 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 + int maBandLength; // MA Band Length + int zigzagDepth; // ZigZag Depth + int zigzagDeviation; // ZigZag Deviation + int zigzagBackStep; // ZigZag Back Step + ENUM_X_PRICE zigzagUppersMode; // ZigZag High Detect Mode + ENUM_X_PRICE zigzagLowersMode; // ZigZag Low Detect Mode + bool hkIgnoreShadows; // HK Remove noises + int hkSmoothingLength; // HK Smoothing Length + ENUM_X_MA_METHOD hkSmoothingMode; // HK Smoothing Method + int atrLength; // ATR Length + double atrMultiplier; // ATR Band Multiplier + int atrSmoothingLength; // ATR Smoothing Length + ENUM_X_PRICE atrUpperPriceType; // ATR Upper Zone Applied To + ENUM_X_PRICE atrLowerPriceType; // ATR Lower Zone Applied To + ENUM_X_MA_METHOD atrSmoothingMode; // ATR Smoothing Method + + // + // Presentation ... + bool showPV; // Show PV + bool showHK; // Show HK + bool showSAR; // Show SAR + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow + bool showMABand; // Show MA Band + bool showHKBand; // Show HK Band + bool showATRBand; // Show ATR Band + bool showZigZag; // Show ZigZag + bool showCyclesMa; // Show Cycles MA + 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) ... + XFIMAInputs() + { + 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 + fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level + fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level + fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 + maBandLength = 7; // MA Band Length + zigzagDepth = 12; // ZigZag Depth + zigzagDeviation = 5; // ZigZag Deviation + zigzagBackStep = 3; // ZigZag Back Step + zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode + zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + hkIgnoreShadows = true; // HK Remove noises + hkSmoothingLength = 21; // HK Smoothing Length + hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method + atrLength = 14; // ATR Length + atrMultiplier = 1.5; // ATR Band Multiplier + atrSmoothingLength = 21; // ATR Smoothing Length + atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To + atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To + atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method + + // + // Presentation ... + showPV = true; // Show PV + showHK = true; // Show HK + showSAR = true; // Show SAR + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow + showMABand = true; // Show MA Band + showHKBand = true; // Show HK Band + showATRBand = true; // Show ATR Band + showZigZag = true; // Show ZigZag + showCyclesMa = true; // Show Cycles MA + 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; + showHK = false; + showSAR = false; + showMAFast = false; + showMASlow = false; + showMABand = false; + showHKBand = false; + showATRBand = false; + showZigZag = false; + showCyclesMa = true; + showFiboZone = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // ATR ... + atrLength > 0 && + atrMultiplier >= 1 && + IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType) && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; + } +}; + +// +// Conditions ... +struct XFIMAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double maFastBuffer[]; + double maSlowBuffer[]; + double sarBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboMiddleBuffer[]; + double fiboLowerBuffer[]; + double zigzagBuffer[]; + double maBandUpperBuffer[]; + double maBandLowerBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkLowBuffer[]; + double hkCloseBuffer[]; + double hkColorBuffer[]; + double hkBandUpperBuffer[]; + double hkBandLowerBuffer[]; + double pbBandUpperBuffer[]; + double pbBandLowerBuffer[]; + double atrBandUpperBuffer[]; + double atrBandLowerBuffer[]; + double scMaBuffer[]; + double mcMaBuffer[]; + double lcMaBuffer[]; + double hcMaBuffer[]; + double maFastStateBuffer[]; + double maSlowStateBuffer[]; + double sarStateBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double hkRawHighBuffer[]; + double hkRawOpenBuffer[]; + double hkRawLowBuffer[]; + double hkRawCloseBuffer[]; + double pbBandRawUpperBuffer[]; + double pbBandRawLowerBuffer[]; + double atrBuffer[]; + double atrBandRawUpperBuffer[]; + double atrBandRawLowerBuffer[]; + double scMaStateBuffer[]; + double mcMaStateBuffer[]; + double lcMaStateBuffer[]; + double hcMaStateBuffer[]; + + // + // Conditions ... + + // + // Constructor ... + XFIMAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + XClean(bars); + + // + XClean(maFastBuffer); + XClean(maSlowBuffer); + XClean(sarBuffer); + XClean(peakBuffer); + XClean(valeBuffer); + XClean(fiboUpperBuffer); + XClean(fiboMiddleBuffer); + XClean(fiboLowerBuffer); + XClean(zigzagBuffer); + XClean(maBandUpperBuffer); + XClean(maBandLowerBuffer); + XClean(hkOpenBuffer); + XClean(hkHighBuffer); + XClean(hkLowBuffer); + XClean(hkCloseBuffer); + XClean(hkColorBuffer); + XClean(hkBandUpperBuffer); + XClean(hkBandLowerBuffer); + XClean(pbBandUpperBuffer); + XClean(pbBandLowerBuffer); + XClean(atrBandUpperBuffer); + XClean(atrBandLowerBuffer); + XClean(scMaBuffer); + XClean(mcMaBuffer); + XClean(lcMaBuffer); + XClean(hcMaBuffer); + XClean(maFastStateBuffer); + XClean(maSlowStateBuffer); + XClean(sarStateBuffer); + XClean(sHHBuffer); + XClean(sLLBuffer); + XClean(mHHBuffer); + XClean(mLLBuffer); + XClean(lHHBuffer); + XClean(lLLBuffer); + XClean(hHHBuffer); + XClean(hLLBuffer); + XClean(hkRawHighBuffer); + XClean(hkRawOpenBuffer); + XClean(hkRawLowBuffer); + XClean(hkRawCloseBuffer); + XClean(pbBandRawUpperBuffer); + XClean(pbBandRawLowerBuffer); + XClean(atrBuffer); + XClean(atrBandRawUpperBuffer); + XClean(atrBandRawLowerBuffer); + XClean(scMaStateBuffer); + XClean(mcMaStateBuffer); + XClean(lcMaStateBuffer); + XClean(hcMaStateBuffer); + + // + // Conditions ... + + // + ArraySetAsSeries(bars, true); + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboMiddleBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(zigzagBuffer, true); + ArraySetAsSeries(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(hkColorBuffer, true); + ArraySetAsSeries(hkBandUpperBuffer, true); + ArraySetAsSeries(hkBandLowerBuffer, true); + ArraySetAsSeries(pbBandUpperBuffer, true); + ArraySetAsSeries(pbBandLowerBuffer, true); + ArraySetAsSeries(atrBandUpperBuffer, true); + ArraySetAsSeries(atrBandLowerBuffer, true); + ArraySetAsSeries(scMaBuffer, true); + ArraySetAsSeries(mcMaBuffer, true); + ArraySetAsSeries(lcMaBuffer, true); + ArraySetAsSeries(hcMaBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(sarStateBuffer, 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(hkRawHighBuffer, true); + ArraySetAsSeries(hkRawOpenBuffer, true); + ArraySetAsSeries(hkRawLowBuffer, true); + ArraySetAsSeries(hkRawCloseBuffer, true); + ArraySetAsSeries(pbBandRawUpperBuffer, true); + ArraySetAsSeries(pbBandRawLowerBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(atrBandRawUpperBuffer, true); + ArraySetAsSeries(atrBandRawLowerBuffer, true); + ArraySetAsSeries(scMaStateBuffer, true); + ArraySetAsSeries(mcMaStateBuffer, true); + ArraySetAsSeries(lcMaStateBuffer, true); + ArraySetAsSeries(hcMaStateBuffer, 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 GetToken(this); + } +}; + +// +// Class ... +class XCXFIMAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + XCMarketPatternDetector *patternDetector; + + // + // Constructors ... + XCXFIMAHelper() + : XCBaseHelper(_Symbol, _Period) + { + patternDetector = new XCMarketPatternDetector(); + } + + // + // Deconstructor ... + ~XCXFIMAHelper() + { + // + delete patternDetector; + ZeroMemory(patternDetector); + } + + // + // Tools ... + + // + // Initialize Helper Cleass ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XFIMAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xfima", + "", // Calculation ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, + mInputs.fiboUpperZoneLevel, + mInputs.fiboMiddleZoneLevel, + mInputs.fiboLowerZoneLevel, + mInputs.sarStep, + mInputs.sarMax, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.maFastLength, + mInputs.maSlowLength, + mInputs.maBandLength, + mInputs.zigzagDepth, + mInputs.zigzagDeviation, + mInputs.zigzagBackStep, + mInputs.zigzagUppersMode, + mInputs.zigzagLowersMode, + mInputs.hkIgnoreShadows, + mInputs.hkSmoothingLength, + mInputs.hkSmoothingMode, + mInputs.atrLength, + mInputs.atrMultiplier, + mInputs.atrSmoothingLength, + mInputs.atrUpperPriceType, + mInputs.atrLowerPriceType, + mInputs.atrSmoothingMode, + "", // Presentation ... + mInputs.showPV, + mInputs.showHK, + mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, + mInputs.showMABand, + mInputs.showHKBand, + mInputs.showATRBand, + mInputs.showZigZag, + mInputs.showCyclesMa, + mInputs.showFiboZone, + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peakArrowCode, + mInputs.valeArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XFIMAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XFIMAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs // + ); + } + + // + // Tools ... + + // + bool GetConditions( + XFIMAConditions &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 // + ); + + // + CopySCMA( + zIndex, + loopback, + conditions.scMaBuffer // + ); + + // + CopySCMAState( + zIndex, + loopback, + conditions.scMaStateBuffer // + ); + + // + CopyMCMA( + zIndex, + loopback, + conditions.mcMaBuffer // + ); + + // + CopyMCMAState( + zIndex, + loopback, + conditions.mcMaStateBuffer // + ); + + // + CopyLCMA( + zIndex, + loopback, + conditions.lcMaBuffer // + ); + + // + CopyLCMAState( + zIndex, + loopback, + conditions.lcMaStateBuffer // + ); + + // + CopyHCMA( + zIndex, + loopback, + conditions.hcMaBuffer // + ); + + // + CopyHCMAState( + zIndex, + loopback, + conditions.hcMaStateBuffer // + ); + + // + CopyMABandUpper( + zIndex, + loopback, + conditions.maBandUpperBuffer // + ); + + // + CopyMABandLower( + zIndex, + loopback, + conditions.maBandLowerBuffer // + ); + + // + 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 // + ); + + // + CopyFiboMiddle( + zIndex, + loopback, + conditions.fiboMiddleBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + CopyZigZag( + zIndex, + loopback, + conditions.zigzagBuffer // + ); + + // + 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 // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyHKRawOpen( + zIndex, + loopback, + conditions.hkRawOpenBuffer // + ); + + // + CopyHKRawHigh( + zIndex, + loopback, + conditions.hkRawHighBuffer // + ); + + // + CopyHKRawLow( + zIndex, + loopback, + conditions.hkRawLowBuffer // + ); + + // + CopyHKRawClose( + zIndex, + loopback, + conditions.hkRawCloseBuffer // + ); + + // + CopyHKColor( + zIndex, + loopback, + conditions.hkColorBuffer // + ); + + // + CopyHKBandUpper( + zIndex, + loopback, + conditions.hkBandUpperBuffer // + ); + + // + CopyHKBandLower( + zIndex, + loopback, + conditions.hkBandLowerBuffer // + ); + + // + CopyPBBandUpper( + zIndex, + loopback, + conditions.pbBandUpperBuffer // + ); + + // + CopyPBBandLower( + zIndex, + loopback, + conditions.pbBandLowerBuffer // + ); + + // + CopyPBRawBandUpper( + zIndex, + loopback, + conditions.pbBandRawUpperBuffer // + ); + + // + CopyPBRawBandLower( + zIndex, + loopback, + conditions.pbBandRawLowerBuffer // + ); + + // + CopyATRBandUpper( + zIndex, + loopback, + conditions.atrBandUpperBuffer // + ); + + // + CopyATRBandLower( + zIndex, + loopback, + conditions.atrBandLowerBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyATRRawBandUpper( + zIndex, + loopback, + conditions.atrBandRawUpperBuffer // + ); + + // + CopyATRRawBandLower( + zIndex, + loopback, + conditions.atrBandRawLowerBuffer // + ); + + // + + + // + // Conditions ... + + // + return result; + } + + // + // Fast MA ... + + // + double GetMAFast( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_LINE, + barIndex // + ); + } + + // + int CopyMAFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_LINE, + start, + count, + asSeries // + ); + } + + // + // Fast MA State ... + + // + double GetMAFastState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_STATE_LINE, + barIndex // + ); + } + + // + int CopyMAFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA ... + + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_LINE, + barIndex // + ); + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA State ... + + // + double GetMASlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyMASlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper MA ... + + // + double GetMABandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyMABandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower MA ... + + // + double GetMABandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyMABandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XPB ... + + // + // Upper PB ... + + // + double GetPBBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyPBBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower PB ... + + // + double GetPBBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyPBBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper PB ... + + // + double GetPBRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyPBRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower PB ... + + // + double GetPBRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyPBRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XATR ... + + // + // Upper ATR ... + + // + double GetATRBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_LINE, + barIndex // + ); + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper ATR ... + + // + double GetATRRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR ... + + // + double GetSAR( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_LINE, + barIndex // + ); + } + + // + int CopySAR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR State ... + + // + double GetSARState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_STATE_LINE, + barIndex // + ); + } + + // + int CopySARState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PEAK_LINE, + barIndex // + ); + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PEAK_LINE, + start, + count, + asSeries // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_VALE_LINE, + barIndex // + ); + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_VALE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Zone ... + + // + // FIBO Upper ... + + // + double GetFiboUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_UPPER_LINE, + barIndex // + ); + } + + // + int CopyFiboUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Middle ... + + // + double GetFiboMiddle( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_MIDDLE_LINE, + barIndex // + ); + } + + // + int CopyFiboMiddle( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_MIDDLE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Lower ... + + // + double GetFiboLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_LOWER_LINE, + barIndex // + ); + } + + // + int CopyFiboLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ZigZag ... + + // + double GetZigZag( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ZIGZAG_LINE, + barIndex // + ); + } + + // + int CopyZigZag( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ZIGZAG_LINE, + start, + count, + asSeries // + ); + } + + // + // CYCLES Range ... + + // + // MAs ... + + // + // SC MA ... + + // + double GetSCMA( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_MA_LINE, + barIndex // + ); + } + + // + int CopySCMA( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_MA_LINE, + start, + count, + asSeries // + ); + } + + // + // SC MA State ... + + // + double GetSCMAState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_MA_STATE_LINE, + barIndex // + ); + } + + // + int CopySCMAState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_MA_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // MC MA ... + + // + double GetMCMA( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_MA_LINE, + barIndex // + ); + } + + // + int CopyMCMA( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_MA_LINE, + start, + count, + asSeries // + ); + } + + // + // MC MA State ... + + // + double GetMCMAState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_MA_STATE_LINE, + barIndex // + ); + } + + // + int CopyMCMAState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_MA_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // LC MA ... + + // + double GetLCMA( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_MA_LINE, + barIndex // + ); + } + + // + int CopyLCMA( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_MA_LINE, + start, + count, + asSeries // + ); + } + + // + // LC MA State ... + + // + double GetLCMAState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_MA_STATE_LINE, + barIndex // + ); + } + + // + int CopyLCMAState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_MA_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // HC MA ... + + // + double GetHCMA( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_MA_LINE, + barIndex // + ); + } + + // + int CopyHCMA( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_MA_LINE, + start, + count, + asSeries // + ); + } + + // + // HC MA State ... + + // + double GetHCMAState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_MA_STATE_LINE, + barIndex // + ); + } + + // + int CopyHCMAState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_MA_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_HH_LINE, + barIndex // + ); + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_LL_LINE, + barIndex // + ); + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_HH_LINE, + barIndex // + ); + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_LL_LINE, + barIndex // + ); + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_HH_LINE, + barIndex // + ); + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_LL_LINE, + barIndex // + ); + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_HH_LINE, + barIndex // + ); + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_LL_LINE, + barIndex // + ); + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK ... + + // + // XHK Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Color ... + + // + double GetHKColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_COLOR_LINE, + barIndex // + ); + } + + // + int CopyHKColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_COLOR_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw ... + + // + // XHK Raw Open ... + + // + double GetHKRawOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKRawOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw High ... + + // + double GetHKRawHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKRawHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw Low ... + + // + double GetHKRawLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKRawLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw Close ... + + // + double GetHKRawClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKRawClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Band ... + + // + // XHK Band Upper ... + + // + double GetHKBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyHKBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Band Lower ... + + // + double GetHKBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyHKBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XFIMAInputs mInputs; // Inputs ... + + // + // XHK Helper ... + + /** + * Validate HK Zone ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param validationLength: int, Validation Length of Zones ... + * @param breakValidLength: int, Break Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * + * @return ( bool ) + */ + bool ValidateHKZone( + XBoxZone &zone, + int validationLength = 1, + int breakValidLength = 3, + bool validateFakeBreakes = true // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + breakValidLength = NormalizeInt(breakValidLength, 2); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Requirements ... + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double close = EMPTY_VALUE; + + // + int count = 0; + int start = zone.FromIndex() + 1; + int end = start + validationLength; + + // + // Validate Before ... + for (int i = start; i < end; i++) + { + // + // Reading HK ... + low = GetHKLow(i); + high = GetHKHigh(i); + result = + NotEmptyZero(low) && + NotEmptyZero(high); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low > zone.lower + : high < zone.upper; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = start; i < end; i++) + { + // + // Read HK ... + low = GetHKLow(i); + high = GetHKHigh(i); + result = + NotEmptyZero(low) && + NotEmptyZero(high); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low > zone.lower + : high < zone.upper; + if (!result) + { + // + // Check For Fake Breake ... + if (validateFakeBreakes && breakValidLength > 0) + { + // + result = i - 1 >= 0; + if (result) + { + // + for (int j = i - 1; j >= zone.ToIndex(); j--) + { + // + // Reading HK ... + close = GetHKClose(j); + result = NotEmptyZero(close); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? close > zone.upper + : close < zone.lower; + if (result) + { + // + result = MathAbs(j - i) <= breakValidLength; + if (result) + { + break; + } + } + } + } + } + + // + if (!result) + { + break; + } + } + } + } + + // + // Cleanup Resource ... + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Helpers/x-saherelm.xom1.helper.mq5 b/BKPS/14041018/Helpers/x-saherelm.xom1.helper.mq5 new file mode 100644 index 0000000..b461865 --- /dev/null +++ b/BKPS/14041018/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/14041018/Indicators/x-saherelm.x121.xcatb.ex5 b/BKPS/14041018/Indicators/x-saherelm.x121.xcatb.ex5 new file mode 100644 index 0000000..d3b9f8c Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.x121.xcatb.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.x121.xcatb.mq5 b/BKPS/14041018/Indicators/x-saherelm.x121.xcatb.mq5 new file mode 100644 index 0000000..83f7eb5 --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.x121.xcatb.mq5 @@ -0,0 +1,2707 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Indicators/x-saherelm.x121.xcc.ex5 b/BKPS/14041018/Indicators/x-saherelm.x121.xcc.ex5 new file mode 100644 index 0000000..80874ad Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.x121.xcc.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14041018/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..8ff56b7 --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.x121.xcc.mq5 @@ -0,0 +1,438 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Indicators/x-saherelm.x121.xct.ex5 b/BKPS/14041018/Indicators/x-saherelm.x121.xct.ex5 new file mode 100644 index 0000000..7ba2565 Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.x121.xct.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14041018/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..dc8542c --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,263 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Indicators/x-saherelm.x121.xki.ex5 b/BKPS/14041018/Indicators/x-saherelm.x121.xki.ex5 new file mode 100644 index 0000000..565eeae Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.x121.xki.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.x121.xki.mq5 b/BKPS/14041018/Indicators/x-saherelm.x121.xki.mq5 new file mode 100644 index 0000000..91fd20d --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.x121.xki.mq5 @@ -0,0 +1,1753 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XKI +// Description: a Kijunsen Based 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 XKI Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +#define ShortName "XKI" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// #region Inputs ... +// +input group "Calculation"; +input int kiFastLength = 26; // KI Fast Length +input int kiSlowLength = 104; // KI Slow Length +input int kiSuperSlowLength = 208; // KI Super Slow Length +input int maFastLength = 26; // MA Fast Length +input int maSlowLength = 104; // MA Slow Length +input int maSuperSlowLength = 208; // MA Super Slow Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Mode +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To +input int rsiLength = 14; // RSI Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input double rsiBullishConfirmation = 55; // RSI Bullish Confirmation Level +input double rsiBearishConfirmation = 45; // RSI Bearish Confirmation Level +input int kiWaveSmoothingLength = 14; // RSI KI Wave Smoothing Length +input ENUM_X_MA_METHOD kiWaveSmoothingMode = X_MA_MODE_EMA; // RSI KI Wave Smoothing Method +input double rsiMultiplier = 0.5; // RSI Multiplier +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier +input int atrSmoothingLength = 14; // ATR Smoothing Length +input ENUM_X_MA_METHOD atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Price Type +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Price Type + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showKIFast = true; // Show KI Fast +input bool showKISlow = true; // Show KI Slow +input bool showKISuperSlow = true; // Show KI Super Slow +input bool showMaFast = true; // Show Ma Fast +input bool showMaSlow = true; // Show MA Slow +input bool showMaSuperSlow = true; // Show MA Super Slow +input bool showKIWave = true; // Show KI Wave +input bool showKIUpper = true; // Show KI Upper +input bool showKILower = true; // Show KI Lower + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +input int peakArrowCode = 159; // Peaks Arrow Code +input int valeArrowCode = 159; // Vales Arrow Code +// #endregion + +// #region 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 +// #endregion + +// #region Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 25 +#property indicator_plots 11 + +// #region Plot Buffers ... +// #region KI ... +// +#define kiBufferIndex 0 +#define kiBufferPlotIndex 0 +double kiBuffer[]; + +// +#define kiColorBufferIndex 1 +double kiColorBuffer[]; + +// +#property indicator_label1 "KI Fast" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 +// #endregion + +// #region KI Wave ... +// +#define kiWaveBufferIndex 2 +#define kiWaveBufferPlotIndex 1 +double kiWaveBuffer[]; + +// +#define kiWaveColorBufferIndex 3 +double kiWaveColorBuffer[]; + +// +#property indicator_label2 "KI Wave" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 +// #endregion + +// #region KI Upper ... +// +#define kiUpperBufferIndex 4 +#define kiUpperBufferPlotIndex 2 +double kiUpperBuffer[]; + +// +#property indicator_label3 "KI Upper" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAqua +#property indicator_style3 STYLE_DASH +#property indicator_width3 1 +// #endregion + +// #region KI Lower ... +// +#define kiLowerBufferIndex 5 +#define kiLowerBufferPlotIndex 3 +double kiLowerBuffer[]; + +// +#property indicator_label4 "KI Lower" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_DASH +#property indicator_width4 1 +// #endregion + +// #region MA Fast ... +// +#define maFastBufferIndex 6 +#define maFastBufferPlotIndex 4 +double maFastBuffer[]; + +// +#property indicator_label5 "MA Fast" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrLime +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 +// #endregion + +// #region MA Slow ... +// +#define maSlowBufferIndex 7 +#define maSlowBufferPlotIndex 5 +double maSlowBuffer[]; + +// +#property indicator_label6 "MA Slow" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrRed +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 +// #endregion + +// #region KI Slow ... +// +#define kiSlowBufferIndex 8 +#define kiSlowBufferPlotIndex 6 +double kiSlowBuffer[]; + +// +#define kiSlowColorBufferIndex 9 +double kiSlowColorBuffer[]; + +// +#property indicator_label7 "KI Slow" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style7 STYLE_SOLID +#property indicator_width7 2 +// #endregion + +// #region KI Super Slow ... +// +#define kiSuperSlowBufferIndex 10 +#define kiSuperSlowBufferPlotIndex 7 +double kiSuperSlowBuffer[]; + +// +#define kiSuperSlowColorBufferIndex 11 +double kiSuperSlowColorBuffer[]; + +// +#property indicator_label8 "KI Super Slow" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style8 STYLE_SOLID +#property indicator_width8 2 +// #endregion + +// #region MA Super Slow ... +// +#define maSuperSlowBufferIndex 12 +#define maSuperSlowBufferPlotIndex 8 +double maSuperSlowBuffer[]; + +// +#property indicator_label9 "MA Super Slow" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrMagenta +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 +// #endregion + +// #region PV ... +// +// PEAKS ... + +// +#define peakBufferIndex 13 +#define peakBufferPlotIndex 9 +double peakBuffer[]; + +// +#property indicator_label10 "PEAK" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrMagenta +#property indicator_width10 3 + +// +// VALES ... + +// +#define valeBufferIndex 14 +#define valeBufferPlotIndex 10 +double valeBuffer[]; + +// +#property indicator_label11 "VALE" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrAqua +#property indicator_width11 3 +// #endregion +// #endregion + +// +#define mLastBufferIndex 14 + +// #region Data Buffers ... +// +#define kiStateBufferIndex mLastBufferIndex + 1 +double kiStateBuffer[]; + +// +#define atrBufferIndex mLastBufferIndex + 2 +double atrBuffer[]; + +// +#define atrRawUpperBufferIndex mLastBufferIndex + 3 +double atrRawUpperBuffer[]; + +// +#define atrRawLowerBufferIndex mLastBufferIndex + 4 +double atrRawLowerBuffer[]; + +// +#define rsiBufferIndex mLastBufferIndex + 5 +double rsiBuffer[]; + +// +#define kiWaveRawBufferIndex mLastBufferIndex + 6 +double kiWaveRawBuffer[]; + +// +#define kiWaveStateBufferIndex mLastBufferIndex + 7 +double kiWaveStateBuffer[]; + +// +#define kiSlowStateBufferIndex mLastBufferIndex + 8 +double kiSlowStateBuffer[]; + +// +#define atrSmoothedBufferIndex mLastBufferIndex + 9 +double atrSmoothedBuffer[]; + +// +#define kiSuperSlowStateBufferIndex mLastBufferIndex + 10 +double kiSuperSlowStateBuffer[]; +// #endregion +// #endregion + +// #region Variables, Properties and etc ... +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Handlers ... +int atrHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; +int maSuperSlowHandler = INVALID_HANDLE; +// #endregion + +// #region Event Handlers ... +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + 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(); + + // + // 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 + + // + // De Initialize all Handlers and etc ... + + // + // ATR ... + if (atrHandler != INVALID_HANDLE) + { + IndicatorRelease(atrHandler); + } + + // + // RSI ... + if (rsiHandler != INVALID_HANDLE) + { + IndicatorRelease(rsiHandler); + } + + // + // MA Fast ... + if (maFastHandler != INVALID_HANDLE) + { + IndicatorRelease(maFastHandler); + } + + // + // MA Slow ... + if (maSlowHandler != INVALID_HANDLE) + { + IndicatorRelease(maSlowHandler); + } + + // + // MA Super Slow ... + if (maSuperSlowHandler != INVALID_HANDLE) + { + IndicatorRelease(maSuperSlowHandler); + } +} + +/** + * 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); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // MA ... + int maFastCalculatedBars = BarsCalculated(maFastHandler); + int maSlowCalculatedBars = BarsCalculated(maSlowHandler); + int maSuperSlowCalculatedBars = BarsCalculated(maSuperSlowHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + maSuperSlowCalculatedBars >= 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); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // MA ... + int copiedMAFasts = CopyBuffer(maFastHandler, MAIN_LINE, 0, limit, maFastBuffer); + int copiedMASlows = CopyBuffer(maSlowHandler, MAIN_LINE, 0, limit, maSlowBuffer); + int copiedMASuperSlows = CopyBuffer(maSuperSlowHandler, MAIN_LINE, 0, limit, maSuperSlowBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedATRs >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + copiedMASuperSlows >= 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; +} +// #endregion + +// #region 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 = + // + // KI ... + kiFastLength >= 5 && + kiSlowLength > kiFastLength && + kiSuperSlowLength > kiSlowLength && + // + // MA ... + maFastLength >= 2 && + maSlowLength > maFastLength && + maSuperSlowLength > maSlowLength && + // + // ATR ... + atrLength >= 5 && + // + // RSI ... + rsiLength >= 5 && + rsiBullishConfirmation > 0 && + rsiBullishConfirmation < 100 && + rsiBearishConfirmation > 0 && + rsiBearishConfirmation < 100 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(kiFastLength, atrLength); + result = MathMax(result, rsiLength); + result = MathMax(result, kiSlowLength); + result = MathMax(result, maFastLength); + result = MathMax(result, maSlowLength); + result = MathMax(result, maSuperSlowLength); + result = MathMax(result, kiSuperSlowLength); + + // + if (atrSmoothingLength > 0) + { + result = MathMax(result, atrSmoothingLength); + } + if (kiWaveSmoothingLength > 0) + { + result = MathMax(result, kiWaveSmoothingLength); + } + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // #region KI ... + // + ArraySetAsSeries(kiBuffer, true); + SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKIFast); + PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiColorBuffer, true); + SetIndexBuffer(kiColorBufferIndex, kiColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(kiStateBuffer, true); + SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); + // #endregion + + // #region KI Slow ... + // + ArraySetAsSeries(kiSlowBuffer, true); + SetIndexBuffer(kiSlowBufferIndex, kiSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiSlowBufferPlotIndex, PLOT_SHOW_DATA, showKISlow); + PlotIndexSetDouble(kiSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiSlowColorBuffer, true); + SetIndexBuffer(kiSlowColorBufferIndex, kiSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(kiSlowStateBuffer, true); + SetIndexBuffer(kiSlowStateBufferIndex, kiSlowStateBuffer, INDICATOR_CALCULATIONS); + // #endregion + + // #region KI Super Slow ... + // + ArraySetAsSeries(kiSuperSlowBuffer, true); + SetIndexBuffer(kiSuperSlowBufferIndex, kiSuperSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiSuperSlowBufferPlotIndex, PLOT_SHOW_DATA, showKISuperSlow); + PlotIndexSetDouble(kiSuperSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiSuperSlowColorBuffer, true); + SetIndexBuffer(kiSuperSlowColorBufferIndex, kiSuperSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(kiSuperSlowStateBuffer, true); + SetIndexBuffer(kiSuperSlowStateBufferIndex, kiSuperSlowStateBuffer, INDICATOR_CALCULATIONS); + // #endregion + + // #region KI Upper ... + // + ENUM_DRAW_TYPE kiUpperDrawType = showKIUpper ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(kiUpperBuffer, true); + SetIndexBuffer(kiUpperBufferIndex, kiUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiUpperBufferPlotIndex, PLOT_SHOW_DATA, showKIUpper); + PlotIndexSetInteger(kiUpperBufferPlotIndex, PLOT_DRAW_TYPE, kiUpperDrawType); + PlotIndexSetDouble(kiUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + // #endregion + + // #region KI Lower ... + // + ENUM_DRAW_TYPE kiLowerDrawType = showKILower ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(kiLowerBuffer, true); + SetIndexBuffer(kiLowerBufferIndex, kiLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiLowerBufferPlotIndex, PLOT_SHOW_DATA, showKILower); + PlotIndexSetInteger(kiLowerBufferPlotIndex, PLOT_DRAW_TYPE, kiLowerDrawType); + PlotIndexSetDouble(kiLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + // #endregion + + // #region KI Wave ... + // + ArraySetAsSeries(kiWaveBuffer, true); + SetIndexBuffer(kiWaveBufferIndex, kiWaveBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiWaveBufferPlotIndex, PLOT_SHOW_DATA, showKIWave); + PlotIndexSetDouble(kiWaveBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiWaveColorBuffer, true); + SetIndexBuffer(kiWaveColorBufferIndex, kiWaveColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(kiWaveRawBuffer, true); + SetIndexBuffer(kiWaveRawBufferIndex, kiWaveRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(kiWaveStateBuffer, true); + SetIndexBuffer(kiWaveStateBufferIndex, kiWaveStateBuffer, INDICATOR_CALCULATIONS); + // #endregion + + // #region PV ... + // + // 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); + // #endregion + + // #region ATR ... + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrSmoothedBuffer, true); + SetIndexBuffer(atrSmoothedBufferIndex, atrSmoothedBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrRawUpperBuffer, true); + SetIndexBuffer(atrRawUpperBufferIndex, atrRawUpperBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrRawLowerBuffer, true); + SetIndexBuffer(atrRawLowerBufferIndex, atrRawLowerBuffer, INDICATOR_CALCULATIONS); + // #endregion + + // #region MA ... + // #region Fast ... + // + ENUM_DRAW_TYPE maFastDrawType = showMaFast ? DRAW_LINE : DRAW_NONE; + + // + // Fast ... + ArraySetAsSeries(maFastBuffer, true); + SetIndexBuffer(maFastBufferIndex, maFastBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maFastBufferPlotIndex, PLOT_SHOW_DATA, showMaFast); + PlotIndexSetInteger(maFastBufferPlotIndex, PLOT_DRAW_TYPE, maFastDrawType); + PlotIndexSetDouble(maFastBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + // #endregion + + // #region Slow ... + // + ENUM_DRAW_TYPE maSlowDrawType = showMaSlow ? DRAW_LINE : DRAW_NONE; + + // + // Slow ... + ArraySetAsSeries(maSlowBuffer, true); + SetIndexBuffer(maSlowBufferIndex, maSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maSlowBufferPlotIndex, PLOT_SHOW_DATA, showMaSlow); + PlotIndexSetInteger(maSlowBufferPlotIndex, PLOT_DRAW_TYPE, maSlowDrawType); + PlotIndexSetDouble(maSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + // #endregion + + // #region Super Slow ... + // + ENUM_DRAW_TYPE maSuperSlowDrawType = showMaSuperSlow ? DRAW_LINE : DRAW_NONE; + + // + // Slow ... + ArraySetAsSeries(maSuperSlowBuffer, true); + SetIndexBuffer(maSuperSlowBufferIndex, maSuperSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maSuperSlowBufferPlotIndex, PLOT_SHOW_DATA, showMaSuperSlow); + PlotIndexSetInteger(maSuperSlowBufferPlotIndex, PLOT_DRAW_TYPE, maSuperSlowDrawType); + PlotIndexSetDouble(maSuperSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + // #endregion + // #endregion +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Fast ... + maFastHandler = iMA( + _Symbol, + _Period, + maFastLength, + 0, + maMethod, + maAppliedTo // + ); + result = maFastHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Slow ... + maSlowHandler = iMA( + _Symbol, + _Period, + maSlowLength, + 0, + maMethod, + maAppliedTo // + ); + result = maSlowHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Super Slow ... + maSuperSlowHandler = iMA( + _Symbol, + _Period, + maSuperSlowLength, + 0, + maMethod, + maAppliedTo // + ); + result = maSuperSlowHandler != 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[] // +) +{ + // + // 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 ... + + // #region PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion + + // #region KI ... + CalculateKI( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion + + // #region KI Slow ... + CalculateKISlow( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion + + // #region KI Super Slow ... + CalculateKISuperSlow( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion + + // #region ATR (Ki Upper/Lower) ... + CalculateATR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion + + // #region RSI (Ki Wave) ... + CalculateRSI( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion +} + +/** + * Calculate KI Bufer ... + * + * @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(kiFastLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiFastLength, 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 = + !showKIFast + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKIFast + ? hideColorIDX + : bearishColorIDX; + } + kiStateBuffer[barIndex] = iKIState; + kiColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + +/** + * Calculate KI Slow Bufer ... + * + * @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 CalculateKISlow( + 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 + : kiSlowBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiSlowLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiSlowLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiSlowBuffer[barIndex] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKISlow + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKISlow + ? hideColorIDX + : bearishColorIDX; + } + kiSlowStateBuffer[barIndex] = iKIState; + kiSlowColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + +/** + * Calculate KI Super Slow Bufer ... + * + * @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 CalculateKISuperSlow( + 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 + : kiSuperSlowBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiSuperSlowLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiSuperSlowLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiSuperSlowBuffer[barIndex] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKISuperSlow + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKISuperSlow + ? hideColorIDX + : bearishColorIDX; + } + kiSuperSlowStateBuffer[barIndex] = iKIState; + kiSuperSlowColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + +/** + * Calculate PV Bufer ... + * + * @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; + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + // Calculate Peak ... + double lastPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double lastVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iPeak = lastPeak; + double iVale = lastVale; + if (isInited) + { + // + int length = maxLength; + + // + double iLL = iBar.FindLowest(length, MODE_LOW); + double iHH = iBar.FindHighest(length, MODE_HIGH); + + // + double iLL2 = iBar.FindLowest(length / 2, MODE_LOW); + double iHH2 = iBar.FindHighest(length / 2, MODE_HIGH); + + // + iPeak = iHH == iHH2 ? iHH : lastPeak; + iVale = iLL == iLL2 ? iLL : lastVale; + + // + lastPeak = iPeak; + lastVale = iVale; + } + else + { + // + iPeak = lastPeak; + iVale = lastVale; + } + peakBuffer[barIndex] = iPeak; + valeBuffer[barIndex] = iVale; + + // + iBar.Clean(); +} + +/** + * Calculate ATR and Ki Upper/Lower Buffers ... + * + * @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 CalculateATR( + 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 iKI = kiBuffer[barIndex]; + double iAtr = atrBuffer[barIndex]; + double iAppliedAtr = atrMultiplier <= 0 + ? iAtr + : atrMultiplier * iAtr; + + // + double iPriceMid = 0; + if (IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType)) + { + // + double iUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + iPriceMid = ((iUpperPrice - iLowerPrice) / 2); + } + + // + double iUpperValue = iKI + iPriceMid + iAppliedAtr; + double iLowerValue = iKI - iPriceMid - iAppliedAtr; + + // + atrRawUpperBuffer[barIndex] = iUpperValue; + atrRawLowerBuffer[barIndex] = iLowerValue; + + // + // Check Can Smooth Atr ... + if (IsXValid(atrSmoothingMode) && + atrSmoothingLength > 0) + { + // + // Smoothed ATR ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrBuffer, + atrSmoothedBuffer, + atrSmoothingMode // + ); + + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrRawUpperBuffer, + kiUpperBuffer, + atrSmoothingMode // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrRawLowerBuffer, + kiLowerBuffer, + atrSmoothingMode // + ); + } + else + { + // + atrSmoothedBuffer[barIndex] = iAtr; + kiUpperBuffer[barIndex] = iUpperValue; + kiLowerBuffer[barIndex] = iLowerValue; + } +} + +/** + * Calculate RSI and Ki Wave Buffers ... + * + * @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 CalculateRSI( + 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 iKI = kiBuffer[barIndex]; + double iRsi = rsiBuffer[barIndex]; + double iAppliedRsi = rsiMultiplier <= 0 + ? iRsi + : rsiMultiplier * iRsi; + + // + double iValue = iKI + iAppliedRsi; + + // + double iState = + iRsi >= rsiBullishConfirmation + ? bullishState + : iRsi <= rsiBearishConfirmation + ? bearishState + : neuturalState; + double iColor = + iRsi >= rsiBullishConfirmation + ? bullishColorIDX + : iRsi <= rsiBearishConfirmation + ? bearishColorIDX + : neuturalColorIDX; + if (!showKIWave) + { + iColor = hideColorIDX; + } + + // + kiWaveRawBuffer[barIndex] = iValue; + kiWaveColorBuffer[barIndex] = iColor; + kiWaveStateBuffer[barIndex] = iState; + + // + // Check Can Smooth Atr ... + if (IsXValid(kiWaveSmoothingMode) && + kiWaveSmoothingLength > 0) + { + // + // Ki Wave ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + kiWaveSmoothingLength, + kiWaveRawBuffer, + kiWaveBuffer, + kiWaveSmoothingMode // + ); + } + else + { + // + kiWaveBuffer[barIndex] = iValue; + } +} +// #endregion \ No newline at end of file diff --git a/BKPS/14041018/Indicators/x-saherelm.x121.xma.ex5 b/BKPS/14041018/Indicators/x-saherelm.x121.xma.ex5 new file mode 100644 index 0000000..6251114 Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.x121.xma.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.x121.xma.mq5 b/BKPS/14041018/Indicators/x-saherelm.x121.xma.mq5 new file mode 100644 index 0000000..5e72fb8 --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.x121.xma.mq5 @@ -0,0 +1,2280 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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.DrawBarArrow( + 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/14041018/Indicators/x-saherelm.xfima.ex5 b/BKPS/14041018/Indicators/x-saherelm.xfima.ex5 new file mode 100644 index 0000000..bd86584 Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.xfima.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.xfima.mq5 b/BKPS/14041018/Indicators/x-saherelm.xfima.mq5 new file mode 100644 index 0000000..48884e2 --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.xfima.mq5 @@ -0,0 +1,3232 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XFIMA +// 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 XFIMA Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +#define ShortName "XFIMA" + +// +// 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 fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // 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 = 21; // Slow MA Length +input int maBandLength = 21; // MA Band Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode +input bool hkIgnoreShadows = true; // HK Remove noises +input int hkSmoothingLength = 21; // HK Smoothing Length +input ENUM_X_MA_METHOD hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method +input int atrLength = 14; // ATR Length +input double atrMultiplier = 1.5; // ATR Band Multiplier +input int atrSmoothingLength = 21; // ATR Smoothing Length +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 atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showHK = true; // Show HK +input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showMABand = true; // Show MA Band +input bool showHKBand = true; // Show HK Band +input bool showATRBand = true; // Show ATR Band +input bool showZigZag = true; // Show ZigZag +input bool showCyclesMa = true; // Show Cycles MA +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 57 +#property indicator_plots 22 + +// +// 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, clrLime, clrLime, clrLime // 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, clrRed, clrRed, clrRed // 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 Middle ... + +// +#define fiboMiddleBufferIndex 9 +#define fiboMiddleBufferPlotIndex 6 +double fiboMiddleBuffer[]; + +// +#property indicator_label7 "FIBMID" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_width7 2 + +// +// FIBO Lower ... + +// +#define fiboLowerBufferIndex 10 +#define fiboLowerBufferPlotIndex 7 +double fiboLowerBuffer[]; + +// +#property indicator_label8 "FIBLO" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrMagenta +#property indicator_width8 2 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 11 +#define zigzagBufferPlotIndex 8 +double zigzagBuffer[]; + +// +#property indicator_label9 "XZG" +#property indicator_type9 DRAW_SECTION +#property indicator_color9 clrYellow +#property indicator_width9 2 + +// +// MA Upper ... + +// +#define maBandUpperBufferIndex 12 +double maBandUpperBuffer[]; + +// +#define maBandUpperBufferPlotIndex 9 +#property indicator_label10 "UpperMA" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrLime +#property indicator_width10 2 + +// +// MA Lower ... + +// +#define maBandLowerBufferIndex 13 +double maBandLowerBuffer[]; + +// +#define maBandLowerBufferPlotIndex 10 +#property indicator_label11 "LowerMA" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrRed +#property indicator_width11 2 + +// +// XHK ... + +// +#define hkOpenBufferIndex 14 +double hkOpenBuffer[]; + +// +#define hkHighBufferIndex 15 +double hkHighBuffer[]; + +// +#define hkLowBufferIndex 16 +double hkLowBuffer[]; + +// +#define hkCloseBufferIndex 17 +double hkCloseBuffer[]; + +// +#define hkColorBufferIndex 18 +double hkColorBuffer[]; + +// +#define hkBufferPlotIndex 11 +#property indicator_label12 "XHK Open;XHK High;XHK Low;XHK Close" +#property indicator_type12 DRAW_COLOR_CANDLES +#property indicator_color12 CLR_NONE, clrAqua, clrMagenta, clrGray + +// +#define hkBandUpperBufferIndex 19 +double hkBandUpperBuffer[]; + +// +#define hkBandUpperBufferPlotIndex 12 +#property indicator_label13 "UpperHK" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrAqua +#property indicator_width13 2 + +// +#define hkBandLowerBufferIndex 20 +double hkBandLowerBuffer[]; + +// +#define hkBandLowerBufferPlotIndex 13 +#property indicator_label14 "LowerHK" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrMagenta +#property indicator_width14 2 + +// +// PB Upper ... + +// +#define pbBandUpperBufferIndex 21 +double pbBandUpperBuffer[]; + +// +#define pbBandUpperBufferPlotIndex 14 +#property indicator_label15 "UpperPB" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrRoyalBlue +#property indicator_width15 2 + +// +// PB Lower ... + +// +#define pbBandLowerBufferIndex 22 +double pbBandLowerBuffer[]; + +// +#define pbBandLowerBufferPlotIndex 15 +#property indicator_label16 "LowerPB" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrRoyalBlue +#property indicator_width16 2 + +// +// ATR Upper ... + +// +#define atrBandUpperBufferIndex 23 +double atrBandUpperBuffer[]; + +// +#define atrBandUpperBufferPlotIndex 16 +#property indicator_label17 "UpperATR" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrOrange +#property indicator_width17 2 + +// +// ATR Lower ... + +// +#define atrBandLowerBufferIndex 24 +double atrBandLowerBuffer[]; + +// +#define atrBandLowerBufferPlotIndex 17 +#property indicator_label18 "LowerATR" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrOrange +#property indicator_width18 2 + +// +#define scMaBufferIndex 25 +double scMaBuffer[]; + +// +#define scMaBufferPlotIndex 18 +#property indicator_label19 "SCMA" +#property indicator_type19 DRAW_LINE +#property indicator_color19 clrChocolate +#property indicator_style19 STYLE_DASHDOTDOT +#property indicator_width19 2 + +// +#define mcMaBufferIndex 26 +double mcMaBuffer[]; + +// +#define mcMaBufferPlotIndex 19 +#property indicator_label20 "MCMA" +#property indicator_type20 DRAW_LINE +#property indicator_color20 clrChocolate +#property indicator_style20 STYLE_DASHDOTDOT +#property indicator_width20 2 + +// +#define lcMaBufferIndex 27 +double lcMaBuffer[]; + +// +#define lcMaBufferPlotIndex 20 +#property indicator_label21 "LCMA" +#property indicator_type21 DRAW_LINE +#property indicator_color21 clrChocolate +#property indicator_style21 STYLE_DASHDOTDOT +#property indicator_width21 2 + +// +#define hcMaBufferIndex 28 +double hcMaBuffer[]; + +// +#define hcMaBufferPlotIndex 21 +#property indicator_label22 "HCMA" +#property indicator_type22 DRAW_LINE +#property indicator_color22 clrChocolate +#property indicator_style22 STYLE_DASHDOTDOT +#property indicator_width22 2 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 28 + +// +// 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[]; + +// +// ZigZag ... + +// +#define highsBufferIndex mLastBufferIndex + 12 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 13 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 14 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 15 +double lowsTimeBuffer[]; + +// +// XHK Data ... + +// +#define hkRawHighBufferIndex mLastBufferIndex + 16 +double hkRawHighBuffer[]; + +// +#define hkRawOpenBufferIndex mLastBufferIndex + 17 +double hkRawOpenBuffer[]; + +// +#define hkRawLowBufferIndex mLastBufferIndex + 18 +double hkRawLowBuffer[]; + +// +#define hkRawCloseBufferIndex mLastBufferIndex + 19 +double hkRawCloseBuffer[]; + +// +// XPB Data ... + +// +#define pbBandRawUpperBufferIndex mLastBufferIndex + 20 +double pbBandRawUpperBuffer[]; + +// +#define pbBandRawLowerBufferIndex mLastBufferIndex + 21 +double pbBandRawLowerBuffer[]; + +// +// XATR Data ... + +// +#define atrBufferIndex mLastBufferIndex + 22 +double atrBuffer[]; + +// +#define atrBandRawUpperBufferIndex mLastBufferIndex + 23 +double atrBandRawUpperBuffer[]; + +// +#define atrBandRawLowerBufferIndex mLastBufferIndex + 24 +double atrBandRawLowerBuffer[]; + +// +// XCMA Data ... + +// +#define scMaStateBufferIndex mLastBufferIndex + 25 +double scMaStateBuffer[]; + +// +#define mcMaStateBufferIndex mLastBufferIndex + 26 +double mcMaStateBuffer[]; + +// +#define lcMaStateBufferIndex mLastBufferIndex + 27 +double lcMaStateBuffer[]; + +// +#define hcMaStateBufferIndex mLastBufferIndex + 28 +double hcMaStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// 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; + +// +int sarHandler = INVALID_HANDLE; +int atrHandler = INVALID_HANDLE; +int scMaHandler = INVALID_HANDLE; +int mcMaHandler = INVALID_HANDLE; +int lcMaHandler = INVALID_HANDLE; +int hcMaHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; +int maUpperHandler = INVALID_HANDLE; +int maLowerHandler = INVALID_HANDLE; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; +int zigzagRecalc = 3; // Number of last extremes for recalculation + +// +double lastZigZagPeak = 0; +datetime lastZigZagPeakTime = NULL; + +// +double lastZigZagVale = 0; +datetime lastZigZagValeTime = NULL; + +// +ENUM_X_MA_METHOD iPBMethod = X_MA_MODE_NONE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Prepare Price Buffer Smoothing Method ... + iPBMethod = ToXMaMethod(maMethod); + + // + 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 + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(sarHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(scMaHandler); + IndicatorRelease(mcMaHandler); + IndicatorRelease(lcMaHandler); + IndicatorRelease(hcMaHandler); + IndicatorRelease(maFastHandler); + IndicatorRelease(maSlowHandler); + IndicatorRelease(maUpperHandler); + IndicatorRelease(maLowerHandler); +} + +/** + * 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // 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); + + // + // MA ... + int maFastCalculatedBars = BarsCalculated(maFastHandler); + int maSlowCalculatedBars = BarsCalculated(maSlowHandler); + int maUpperCalculatedBars = BarsCalculated(maUpperHandler); + int maLowerCalculatedBars = BarsCalculated(maLowerHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // Cycles MA Handlers ... + scCalculatedBars >= maxLength && + mcCalculatedBars >= maxLength && + lcCalculatedBars >= maxLength && + hcCalculatedBars >= maxLength && + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + maUpperCalculatedBars >= maxLength && + maLowerCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= 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 ... + + // + 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); + + // + // MA ... + int copiedMAFasts = CopyBuffer(maFastHandler, MAIN_LINE, 0, limit, maFastBuffer); + int copiedMASlows = CopyBuffer(maSlowHandler, MAIN_LINE, 0, limit, maSlowBuffer); + int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maBandUpperBuffer); + int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maBandLowerBuffer); + + // + // SAR ... + int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // ATR ... + int copiedATRs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // Cycles MA ... + copiedSCs >= limit && + copiedMCs >= limit && + copiedLCs >= limit && + copiedHCs >= limit && + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + copiedMAUppers >= limit && + copiedMALowers >= limit && + // + // SAR ... + copiedSARs >= limit && + // + // ATR ... + copiedATRs >= 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 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // ATR ... + atrLength > 0 && + atrMultiplier >= 1 && + IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + 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); + result = MathMax(result, maBandLength); + result = MathMax(result, atrLength); + + // + 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); + + // + // 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); + + // + // 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); + + // + // 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); + + // + // Middle ... + ArraySetAsSeries(fiboMiddleBuffer, true); + SetIndexBuffer(fiboMiddleBufferIndex, fiboMiddleBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboMiddleBufferPlotIndex, 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); + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Band ... + + // + ENUM_DRAW_TYPE maBandDrawType = showMABand ? DRAW_LINE : DRAW_NONE; + + // + // Upper Band ... + + // + ArraySetAsSeries(maBandUpperBuffer, true); + SetIndexBuffer(maBandUpperBufferIndex, maBandUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetInteger(maBandUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Lower Band ... + + // + ArraySetAsSeries(maBandLowerBuffer, true); + SetIndexBuffer(maBandLowerBufferIndex, maBandLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetInteger(maBandLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // XPB Band ... + + // + // Upper Band ... + + // + ArraySetAsSeries(pbBandUpperBuffer, true); + SetIndexBuffer(pbBandUpperBufferIndex, pbBandUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(pbBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(pbBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetDouble(pbBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Lower Band ... + + // + ArraySetAsSeries(pbBandLowerBuffer, true); + SetIndexBuffer(pbBandLowerBufferIndex, pbBandLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(pbBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(pbBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetDouble(pbBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // XHK ... + + // + // XHK Color ... + ArraySetAsSeries(hkColorBuffer, true); + SetIndexBuffer(hkColorBufferIndex, hkColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkOpenBuffer, true); + SetIndexBuffer(hkOpenBufferIndex, hkOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkHighBuffer, true); + SetIndexBuffer(hkHighBufferIndex, hkHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkLowBuffer, true); + SetIndexBuffer(hkLowBufferIndex, hkLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkCloseBuffer, true); + SetIndexBuffer(hkCloseBufferIndex, hkCloseBuffer, INDICATOR_DATA); + + // + // XHK Band ... + // + ENUM_DRAW_TYPE hkBandDrawType = showHKBand ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(hkBandUpperBuffer, true); + SetIndexBuffer(hkBandUpperBufferIndex, hkBandUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hkBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showHKBand); + PlotIndexSetInteger(hkBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, hkBandDrawType); + PlotIndexSetDouble(hkBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Lower ... + ArraySetAsSeries(hkBandLowerBuffer, true); + SetIndexBuffer(hkBandLowerBufferIndex, hkBandLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hkBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showHKBand); + PlotIndexSetInteger(hkBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, hkBandDrawType); + PlotIndexSetDouble(hkBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // XATR Band ... + // + ENUM_DRAW_TYPE atrBandDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(atrBandUpperBuffer, true); + SetIndexBuffer(atrBandUpperBufferIndex, atrBandUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(atrBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrBandDrawType); + PlotIndexSetDouble(atrBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Lower ... + ArraySetAsSeries(atrBandLowerBuffer, true); + SetIndexBuffer(atrBandLowerBufferIndex, atrBandLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(atrBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrBandDrawType); + PlotIndexSetDouble(atrBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + ArraySetAsSeries(maFastStateBuffer, true); + SetIndexBuffer(maFastStateBufferIndex, maFastStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(maSlowStateBuffer, true); + SetIndexBuffer(maSlowStateBufferIndex, maSlowStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // CYCLES ... + + // + // SC ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + // MC ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + // LC ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); + + // + // HC ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_CALCULATIONS); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // XHK Data ... + + // + ArraySetAsSeries(hkRawHighBuffer, true); + SetIndexBuffer(hkRawHighBufferIndex, hkRawHighBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hkRawOpenBuffer, true); + SetIndexBuffer(hkRawOpenBufferIndex, hkRawOpenBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hkRawLowBuffer, true); + SetIndexBuffer(hkRawLowBufferIndex, hkRawLowBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hkRawCloseBuffer, true); + SetIndexBuffer(hkRawCloseBufferIndex, hkRawCloseBuffer, INDICATOR_CALCULATIONS); + + // + // XPB Data ... + + // + ArraySetAsSeries(pbBandRawUpperBuffer, true); + SetIndexBuffer(pbBandRawUpperBufferIndex, pbBandRawUpperBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(pbBandRawLowerBuffer, true); + SetIndexBuffer(pbBandRawLowerBufferIndex, pbBandRawLowerBuffer, INDICATOR_CALCULATIONS); + + // + // XATR Data ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrBandRawUpperBuffer, true); + SetIndexBuffer(atrBandRawUpperBufferIndex, atrBandRawUpperBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrBandRawLowerBuffer, true); + SetIndexBuffer(atrBandRawLowerBufferIndex, atrBandRawLowerBuffer, INDICATOR_CALCULATIONS); + + // + // MA State ... + + // + // Draw Type ... + ENUM_DRAW_TYPE cyclesMADrawType = showCyclesMa ? DRAW_LINE : DRAW_NONE; + + // + // SC ... + + // + ArraySetAsSeries(scMaBuffer, true); + SetIndexBuffer(scMaBufferIndex, scMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scMaBufferPlotIndex, PLOT_SHOW_DATA, showCyclesMa); + PlotIndexSetDouble(scMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(scMaBufferPlotIndex, PLOT_DRAW_TYPE, cyclesMADrawType); + + // + ArraySetAsSeries(scMaStateBuffer, true); + SetIndexBuffer(scMaStateBufferIndex, scMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // SC ... + + // + ArraySetAsSeries(mcMaBuffer, true); + SetIndexBuffer(mcMaBufferIndex, mcMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcMaBufferPlotIndex, PLOT_SHOW_DATA, showCyclesMa); + PlotIndexSetDouble(mcMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(mcMaBufferPlotIndex, PLOT_DRAW_TYPE, cyclesMADrawType); + + // + ArraySetAsSeries(scMaStateBuffer, true); + SetIndexBuffer(mcMaStateBufferIndex, mcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // LC ... + + // + ArraySetAsSeries(lcMaBuffer, true); + SetIndexBuffer(lcMaBufferIndex, lcMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcMaBufferPlotIndex, PLOT_SHOW_DATA, showCyclesMa); + PlotIndexSetDouble(lcMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(lcMaBufferPlotIndex, PLOT_DRAW_TYPE, cyclesMADrawType); + + // + ArraySetAsSeries(lcMaStateBuffer, true); + SetIndexBuffer(lcMaStateBufferIndex, lcMaStateBuffer, INDICATOR_CALCULATIONS); + + // + // HC ... + + // + ArraySetAsSeries(hcMaBuffer, true); + SetIndexBuffer(hcMaBufferIndex, hcMaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcMaBufferPlotIndex, PLOT_SHOW_DATA, showCyclesMa); + PlotIndexSetDouble(hcMaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hcMaBufferPlotIndex, PLOT_DRAW_TYPE, cyclesMADrawType); + + // + 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; + if (result) + { + // + // Initialized Cycles MA Ribons Length ... + mSCMALength = maBandLength * mSCLength; + mMCMALength = maBandLength * mMCLength; + mLCMALength = maBandLength * mLCLength; + mHCMALength = maBandLength * mHCLength; + + // + result = mSCMALength > 0 && + mMCMALength > mSCMALength && + mLCMALength > mMCMALength && + mHCMALength > mLCMALength; + } + + // + 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; + } + + // + // MA Band Upper ... + maUpperHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_HIGH // + ); + result = maUpperHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Band Lower ... + maLowerHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_LOW // + ); + result = maLowerHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Cycles MA Handler ... + + // + // 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; + } + + // + 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 // + ); + + // + // XHK ... + CalculateHKBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // XATR ... + CalculateATR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Cycles MA Calculation ... + CalculateCyclesMA( + 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, + fiboUpperZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboMid = GetFibonacciLevel( + iPeak, + iVale, + fiboMiddleZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboLo = GetFibonacciLevel( + iPeak, + iVale, + fiboLowerZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + fiboUpperBuffer[barIndex] = iFiboUp; + fiboMiddleBuffer[barIndex] = iFiboMid; + fiboLowerBuffer[barIndex] = iFiboLo; + + // + // XPB ... + + // + double iPBUpper = MathMax(close[barIndex], open[barIndex]); + double iPBLower = MathMin(close[barIndex], open[barIndex]); + + // + pbBandUpperBuffer[barIndex] = iPBUpper; + pbBandRawUpperBuffer[barIndex] = iPBUpper; + + // + pbBandLowerBuffer[barIndex] = iPBLower; + pbBandRawLowerBuffer[barIndex] = iPBLower; + + // + if (IsXValid(iPBMethod) && maBandLength > 0) + { + // + // XPB Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + maBandLength, + pbBandRawUpperBuffer, + pbBandUpperBuffer, + iPBMethod // + ); + + // + // XPB Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + maBandLength, + pbBandRawLowerBuffer, + pbBandLowerBuffer, + iPBMethod // + ); + } +} + +// +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; +} + +/** + * 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 ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = zigzagDepth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < zigzagRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, zigzagDepth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, zigzagDepth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +// +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 + : hkOpenBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : hkCloseBuffer[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)); + + // + bool isBullish = iHKOpenValue < iHKCloseValue; + bool isBearish = iHKOpenValue > iHKCloseValue; + + // + if (hkIgnoreShadows) + { + // + iHKHighValue = isBullish + ? iHKCloseValue + : iHKOpenValue; + + // + iHKLowValue = isBullish + ? iHKOpenValue + : iHKCloseValue; + } + + // + // XHK Buffers ... + hkOpenBuffer[barIndex] = iHKOpenValue; + hkHighBuffer[barIndex] = iHKHighValue; + hkLowBuffer[barIndex] = iHKLowValue; + hkCloseBuffer[barIndex] = iHKCloseValue; + + // + // XHK Raw Bufferss ... + hkRawOpenBuffer[barIndex] = iHKOpenValue; + hkRawHighBuffer[barIndex] = iHKHighValue; + hkRawLowBuffer[barIndex] = iHKLowValue; + hkRawCloseBuffer[barIndex] = iHKCloseValue; + + // + // Smoothing ... + if (IsXValid(hkSmoothingMode) && hkSmoothingLength > 0) + { + // + // XHK Signal ... + + // + // High ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawHighBuffer, + hkHighBuffer, + hkSmoothingMode // + ); + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawOpenBuffer, + hkOpenBuffer, + hkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawLowBuffer, + hkLowBuffer, + hkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + hkSmoothingLength, + hkRawCloseBuffer, + hkCloseBuffer, + hkSmoothingMode // + ); + } + + // + hkBandUpperBuffer[barIndex] = hkHighBuffer[barIndex]; + hkBandLowerBuffer[barIndex] = hkLowBuffer[barIndex]; + + // + // Calculate HK Color ... + double iHKColorValue = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + hkColorBuffer[barIndex] = + showHK + ? iHKColorValue + : hideColorIDX; +} + +// +void CalculateATR( + 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 iAtr = atrBuffer[barIndex]; + double iAppliedAtr = atrMultiplier <= 0 + ? iAtr + : atrMultiplier * iAtr; + double iUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iPriceMid = iLowerPrice + ((iUpperPrice - iLowerPrice) / 2); + + // + double iUpperAtr = iPriceMid + iAppliedAtr; + double iLowerAtr = iPriceMid - iAppliedAtr; + + // + atrBandRawUpperBuffer[barIndex] = iUpperAtr; + atrBandRawLowerBuffer[barIndex] = iLowerAtr; + + // + // Check Can Smooth Atr ... + if (IsXValid(atrSmoothingMode) && + atrSmoothingLength > 0) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrBandRawUpperBuffer, + atrBandUpperBuffer, + atrSmoothingMode // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrBandRawLowerBuffer, + atrBandLowerBuffer, + atrSmoothingMode // + ); + } + else + { + // + atrBandUpperBuffer[barIndex] = iUpperAtr; + atrBandLowerBuffer[barIndex] = iLowerAtr; + } +} + +// +void CalculateCyclesMA( + 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; + + // + // Retrieve Indexed Bar Price for MA States Checking ... + ENUM_X_PRICE iPriceType = X_PRICE_CLOSE; + double iPrice = GetAppliedPrice( + iPriceType, + open, + high, + low, + close, + barIndex // + ); + + // + // SC ... + double iSCMa = scMaBuffer[barIndex]; + double iSCMaColor = iPrice > iSCMa + ? bullishColorIDX + : iPrice < iSCMa + ? bearishColorIDX + : neuturalColorIDX; + double iSCMaState = iPrice > iSCMa + ? bullishState + : iPrice < iSCMa + ? bearishState + : neuturalState; + scMaStateBuffer[barIndex] = iSCMaState; + + // + // MC ... + double iMCMa = mcMaBuffer[barIndex]; + double iMCMaColor = iPrice > iMCMa + ? bullishColorIDX + : iPrice < iMCMa + ? bearishColorIDX + : neuturalColorIDX; + double iMCMaState = iPrice > iMCMa + ? bullishState + : iPrice < iMCMa + ? bearishState + : neuturalState; + mcMaStateBuffer[barIndex] = iMCMaState; + + // + // LC ... + double iLCMa = lcMaBuffer[barIndex]; + double iLCMaColor = iPrice > iLCMa + ? bullishColorIDX + : iPrice < iLCMa + ? bearishColorIDX + : neuturalColorIDX; + double iLCMaState = iPrice > iLCMa + ? bullishState + : iPrice < iLCMa + ? bearishState + : neuturalState; + lcMaStateBuffer[barIndex] = iLCMaState; + + // + // HC ... + double iHCMa = hcMaBuffer[barIndex]; + double iHCMaColor = iPrice > iHCMa + ? bullishColorIDX + : iPrice < iHCMa + ? bearishColorIDX + : neuturalColorIDX; + double iHCMaState = iPrice > iHCMa + ? bullishState + : iPrice < iHCMa + ? bearishState + : neuturalState; + hcMaStateBuffer[barIndex] = iHCMaState; +} + +// +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(); +} + +// +// +// + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Indicators/x-saherelm.xom1.ex5 b/BKPS/14041018/Indicators/x-saherelm.xom1.ex5 new file mode 100644 index 0000000..9099015 Binary files /dev/null and b/BKPS/14041018/Indicators/x-saherelm.xom1.ex5 differ diff --git a/BKPS/14041018/Indicators/x-saherelm.xom1.mq5 b/BKPS/14041018/Indicators/x-saherelm.xom1.mq5 new file mode 100644 index 0000000..ca0ef31 --- /dev/null +++ b/BKPS/14041018/Indicators/x-saherelm.xom1.mq5 @@ -0,0 +1,1398 @@ +/////////////////////////////////////////////////////// +// +// 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 icon "../Images/SaherElm_Logo_Color.ico" +#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/14041018/Libraries/x-saherelm.common.extensions.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.common.extensions.lib.mq5 new file mode 100644 index 0000000..cc2fcf4 --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -0,0 +1,7365 @@ +/////////////////////////////////////////////////////// +// +// 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 IsXValid(string value) +{ + return IsValid(value); +} +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 IsXValid(datetime value) +{ + return IsValid(value); +} +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 IsXValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} +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 IsXValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + return IsValid( + mMethod, + mPeriod // + ); +} +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 mMode = ToSeriesMode(mType); + result = + mMode == MODE_HIGH + ? iHighest( + mSymbol, + mPeriod, + mMode, + mShoulders, + mFromIndex // + ) + : iLowest( + mSymbol, + mPeriod, + mMode, + 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); +} +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); +} +template +void XClean(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; +} + +/** + * Get Applied Price Buffer ... + * + * @param mType: ENUM_X_PRICE, Specified Price Type ... + * @param dest: double, Holds Destination Prices ... + * @param mOpen: double collection, Open Prices ... + * @param mHigh: double collection, High Prices ... + * @param mLow: double collection, Low Prices ... + * @param mClose: double collection, Close Prices ... + * + * @return ( int ) + */ +int GetAppliedPrice( + ENUM_X_PRICE mType, + double &dest[], + const double &mOpen[], // Open Prices + const double &mHigh[], // High Preices + const double &mLow[], // Low Prices + const double &mClose[] // Close Prices +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Check ArraySizes ... + int count = ArraySize(mOpen); + count = MathMin(count, ArraySize(mHigh)); + count = MathMin(count, ArraySize(mClose)); + count = MathMin(count, ArraySize(mLow)); + + // + // Validate ... + if (!IsValidSize(count)) + { + return result; + } + + // + // Loopback ... + for (int i = 0; i < count; i++) + { + // + double iPrice = GetAppliedPrice( + mType, + mOpen[i], + mHigh[i], + mLow[i], + mClose[i] // + ); + + // + Add( + iPrice, + dest // + ); + } + + // + result = ArraySize(dest); + + // + 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 ... +// + +// +// START ATR ... +// + +/** + * Calculate True Range of Specified Bar ... + * + * @param _symbol: string, Symbol ... + * @param _period: ENUM_TIMEFRAMES, period ... + * @param _barIndex: int, Specified Bar Index ... + * @param ignorePC: bool, Ignore Previous Bar ... + * + * @return ( double ) + */ +double GetTrueRange( + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL, + int _barIndex = 0, + bool ignorePC = false // Ignore Previous Close ... +) +{ + // + double result = EMPTY_VALUE; + + // + // Normalize ... + _symbol = NormalizeSymbol(_symbol); + _period = NormalizePeriod(_period); + _barIndex = NormalizeInt(_barIndex, 0); + + // + double _low = iLow(_symbol, _period, _barIndex); + double _high = iHigh(_symbol, _period, _barIndex); + double _pLow = iLow(_symbol, _period, _barIndex + 1); + double _pHigh = iHigh(_symbol, _period, _barIndex + 1); + double _pClose = iClose(_symbol, _period, _barIndex + 1); + + // + double hlDiff = _high - _low; + + // + if (!ignorePC) + { + // + double hpcDiff = MathAbs(_high - _pClose); + double lpcDiff = MathAbs(_high - _pClose); + + // + result = MathMax(hlDiff, hpcDiff); + result = MathMax(result, lpcDiff); + } + else + { + result = hlDiff; + } + + // + return result; +} + +/** + * Calculate ATR ... + * + * @param _symbol: string, Symbol ... + * @param _period: ENUM_TIMEFRAMES, period ... + * @param _barIndex: int, Specified Bar Index ... + * @param _length: int ATR Period ... + * + * @return ( double ) + */ +double GetAverageTrueRange( + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL, + int _barIndex = 0, + int _length = 14 // +) +{ + // + double result = EMPTY_VALUE; + + // + // Normalize ... + _symbol = NormalizeSymbol(_symbol); + _period = NormalizePeriod(_period); + _length = NormalizeInt(_length, 2); + _barIndex = NormalizeInt(_barIndex, 0); + + // + // Collect True Ranges ... + double itr; + double _trs[]; + bool has = false; + int start = _barIndex; + int end = start + _length; + for (int i = start; i < end; i++) + { + // + itr = GetTrueRange( + _symbol, + _period, + _barIndex, + i == end - 1 // Ignore PC ... + ); + has = NotEmptyZero(itr); + if (has) + { + // + Add( + itr, + _trs // + ); + } + } + + // + int count = ArraySize(_trs); + has = HasChild(_trs); + if (!has) + { + return result; + } + + // + result = GetAverage(_trs); + + // + // Cleanup ... + XClean(_trs); + + // + return result; +} + +// +// END ÙŽATR ... +// + +// +// START Linear Regression ... +// + +/** + * Calculate Slope and Intercept for Linear Regression Predictions ... + * + * @param _slope: double, refrence to Hold Calculated Slope ... + * @param _intercept: double, reference to Hold Calculated Intercept ... + * @param xData: double, reference Collection to Provides X-Axis Data for Calculations ... + * @param yData: double, reference Collection to Provides Y-Axis Data for Calculations ... + * + * @return ( int ) + */ +int CalculateSlopeAndIntercept( + double &_slope, + double &_intercept, + double &xData[], + double &yData[] // +) +{ + // + int result = 0; + + // + bool has = false; + + // + _slope = 0; + _intercept = 0; + + // + if (!HasChild(xData) || + !HasChild(yData)) + { + return result; + } + + // + double sumX = 0; + double sumY = 0; + double sumXY = 0; + double sumX2 = 0; + + // + double x = 0; + double y = 0; + int end = MathMin(ArraySize(xData), ArraySize(yData)); + for (int i = 0; i < end; i++) + { + // + double x = xData[i]; + double y = yData[i]; + + // + sumX += x; + sumY += y; + sumXY += x * y; + sumX2 += x * x; + } + + // + int n = end; + double _dividedBy = (n * sumX2 - sumX * sumX); + // if (_dividedBy <= 0 || n <= 0) + // { + // // + // _slope = 0; + // _intercept = 0; + + // // + // result = 0; + // } else { + // // + // _slope = (n * sumXY - sumX * sumY) / _dividedBy; + // _intercept = (sumY - _slope * sumX) / n; + + // // + // result = n; + // } + + // + _slope = (n * sumXY - sumX * sumY) / _dividedBy; + _intercept = (sumY - _slope * sumX) / n; + + // + result = n; + + // + return result; +} + +/** + * Predict Value for Specified X ... + * + * @param _sllope: double, Provided Slope ... + * @param _intercept: double, Provided Intercept ... + * @param _forX: double, Specified XValue ... + * + * @return ( double ) + */ +double PredictValue( + double _slope, + double _intercept, + double _forX // +) +{ + // + double result = 0; + + // + // Validate ... + if (!NotEmpty(_forX) || + !NotEmpty(_slope) || + !NotEmpty(_intercept)) + { + return result; + } + + // + result = (_intercept + (_slope * _forX)); + + // + return result; +} + +// +// END Linear Regression ... +// + +// diff --git a/BKPS/14041018/Libraries/x-saherelm.common.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..6b97b5d --- /dev/null +++ b/BKPS/14041018/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/14041018/Libraries/x-saherelm.common.models.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.common.models.lib.mq5 new file mode 100644 index 0000000..c8e3186 --- /dev/null +++ b/BKPS/14041018/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/14041018/Libraries/x-saherelm.draw.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ab7f39b --- /dev/null +++ b/BKPS/14041018/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/14041018/Libraries/x-saherelm.x-enums.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-enums.lib.mq5 new file mode 100644 index 0000000..4d96a7d --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.x-enums.lib.mq5 @@ -0,0 +1,1553 @@ +/////////////////////////////////////////////////////// +// +// 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; +} +bool IsXValid(ENUM_X_PRICE value) +{ + return IsValid(value); +} + +/** + * 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; +} +ENUM_APPLIED_PRICE ToXAppliedPrice(ENUM_X_PRICE value) +{ + return ToAppliedPrice(value); +} + +/** + * 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; +} +string ToXString(ENUM_X_PRICE value) +{ + return ToString(value); +} + +// +// 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 IsXValid(ENUM_X_BOUNDARY_PRICE value) +{ + return IsValid(value); +} +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; +} +string ToXString(ENUM_X_BOUNDARY_PRICE value) +{ + return ToString(value); +} + +// +// 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 IsXValid(ENUM_X_DIRECTION value) +{ + return IsValid(value); +} +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 IsXBullish(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 IsXBearish(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; +} +ENUM_X_DIRECTION XOpposit(ENUM_X_DIRECTION value) +{ + return Opposit(value); +} + +/** + * 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; +} +string ToXString(ENUM_X_FIBO_LEVELS value) +{ + return ToString(value); +} + +/** + * 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; +} +string ToXString(ENUM_X_SWING_TYPE value) +{ + return ToString(value); +} + +/** + * 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; +} +ENUM_SERIESMODE ToXSeriesMode(ENUM_X_SWING_TYPE value) +{ + return ToSeriesMode(value); +} + +// +// 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; +} +bool IsXValid(ENUM_X_PERIOD_METHOD value) +{ + return IsValid(value); +} + +/** + * 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; +} +string ToXString(ENUM_X_PERIOD_METHOD value) +{ + return ToString(value); +} + +// +// 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 IsXValid(ENUM_X_MARKET_CYCLES value) +{ + return IsValid(value); +} +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; +} +ENUM_X_MARKET_CYCLES ToXCycle(string value) +{ + return ToCycle(value); +} + +/** + * 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; +} +bool IsXValid(ENUM_X_WEEK_DAYS value) +{ + return IsValid(value); +} + +/** + * 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; +} +string ToXString(ENUM_X_WEEK_DAYS value) +{ + return ToString(value); +} + +// +// 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; +} +bool IsXValid(ENUM_X_MA_METHOD value) +{ + return IsValid(value); +} + +/** + * 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; +} +string ToXString(ENUM_X_MA_METHOD value) +{ + return ToString(value); +} + +/** + * Converts MA Method ... + **/ +ENUM_MA_METHOD ToXMaMethod(ENUM_X_MA_METHOD value) +{ + // + ENUM_MA_METHOD result = MODE_SMA; + + // + if (!IsXValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_MA_MODE_EMA: + result = MODE_EMA; + break; + + // + case X_MA_MODE_SMA: + result = MODE_SMA; + break; + + // + case X_MA_MODE_LWMA: + result = MODE_LWMA; + break; + + // + case X_MA_MODE_SMMA: + result = MODE_SMMA; + break; + } + + // + return result; +} +ENUM_X_MA_METHOD ToXMaMethod(ENUM_MA_METHOD value) +{ + // + ENUM_X_MA_METHOD result = X_MA_MODE_NONE; + + // + switch (value) + { + // + case MODE_EMA: + result = X_MA_MODE_EMA; + break; + + // + case MODE_SMA: + result = X_MA_MODE_SMA; + break; + + // + case MODE_LWMA: + result = X_MA_MODE_LWMA; + break; + + // + case MODE_SMMA: + result = X_MA_MODE_SMMA; + break; + } + + // + return result; +} + +// +// END Ma Methods ... +// + +// +// START XPivots ... +// + +// +enum ENUM_X_PIVOT_TYPE +{ + X_PIVOT_TYPE_NONE = 0, // None + X_PIVOT_TYPE_PEAK = 1, // PEAK + X_PIVOT_TYPE_VALE = 2, // VALE +}; + +/** + * Validate ... + * + * @param value: ENUM_X_PIVOT_TYPE ... + * + * @return ( bool ) + */ +bool IsXValid(ENUM_X_PIVOT_TYPE value) +{ + // + bool result = false; + + // + result = value != X_PIVOT_TYPE_NONE; + + // + return result; +} + +/** + * Check Specified Type of Pivot is Peak or not ... + * + * @param value: ENUM_X_PIVOT_TYPE, Specified Type ... + * + * @return ( bool ) + */ +bool IsXPeak(ENUM_X_PIVOT_TYPE value) +{ + // + bool result = false; + + // + result = IsXValid(value) && + value == X_PIVOT_TYPE_PEAK; + + // + return result; +} + +/** + * Check Specified Type of Pivot is Vale or not ... + * + * @param value: ENUM_X_PIVOT_TYPE, Specified Type ... + * + * @return ( bool ) + */ +bool IsXVale(ENUM_X_PIVOT_TYPE value) +{ + // + bool result = false; + + // + result = IsXValid(value) && + value == X_PIVOT_TYPE_VALE; + + // + return result; +} + +/** + * Represent Specified ZigZag Point Type as String ... + * + * @param value: ENUM_X_PIVOT_TYPE ... + * + * @return ( string ) + */ +string ToXString(ENUM_X_PIVOT_TYPE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PIVOT_TYPE_NONE: + result = "XNONE"; + break; + + // + case X_PIVOT_TYPE_PEAK: + result = "XPEAK"; + break; + + // + case X_PIVOT_TYPE_VALE: + result = "XVALE"; + break; + } + + // + return result; + // return EnumToString(value); +} + +// +// END XPivots ... +// + +// \ No newline at end of file diff --git a/BKPS/14041018/Libraries/x-saherelm.x-guard.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-guard.lib.mq5 new file mode 100644 index 0000000..e0e4c05 --- /dev/null +++ b/BKPS/14041018/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/14041018/Libraries/x-saherelm.x-ohcl.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-ohcl.lib.mq5 new file mode 100644 index 0000000..2b7e531 --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.x-ohcl.lib.mq5 @@ -0,0 +1,3082 @@ +/////////////////////////////////////////////////////// +// +// 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 BarAt( + datetime _time, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + _time = NormalizeTime(_time); + + // + result = bar.Init( + symbol, + period, + _time // + ); + + // + 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; + } + + /** + * Detect Highest of Specified Price type in Market ... + * + * @param index: souble, reference to hold detected Value Bar index ... + * @param mLength: int, Specified Loopback Length ... + * @param mPriceType: ENUM_X_PRICE, Specified Price type to Detect ... + * + * @return ( double ) + */ + double FindHighest( + int &index, // Index ... + int mLength, // Loopback ... + ENUM_X_PRICE mPriceType // Price Type ... + ) + { + // + double result = EMPTY_VALUE; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + mLength = NormalizeInt(mLength, 1); + + // + // Validate ... + bool has = IsValid() && + IsXValid(mPriceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int start = Index(); + int end = start + mLength; + double iValue = EMPTY_VALUE; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + has = BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Calculate Price ... + iValue = iBar.GetPrice(mPriceType); + + // + // Compare Price With Prev Detected ... + has = !NotEmptyZero(result) + ? true + : iValue > result; + if (has) + { + // + index = i; + result = iValue; + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + 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; + } + + /** + * Detect Lowest of Specified Price type in Market ... + * + * @param index: souble, reference to hold detected Value Bar index ... + * @param mLength: int, Specified Loopback Length ... + * @param mPriceType: ENUM_X_PRICE, Specified Price type to Detect ... + * + * @return ( double ) + */ + double FindLowest( + int &index, // Index ... + int mLength, // Loopback ... + ENUM_X_PRICE mPriceType // Price Type ... + ) + { + // + double result = EMPTY_VALUE; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + mLength = NormalizeInt(mLength, 1); + + // + // Validate ... + bool has = IsValid() && + IsXValid(mPriceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int start = Index(); + int end = start + mLength; + double iValue = EMPTY_VALUE; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + has = BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Calculate Price ... + iValue = iBar.GetPrice(mPriceType); + + // + // Compare Price With Prev Detected ... + has = !NotEmptyZero(result) + ? true + : iValue < result; + if (has) + { + // + index = i; + result = iValue; + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + 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; + } + + // + // Same Checkers ... + + // + bool IsSameAs(XOHCL &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + IsSameTime(item) && + IsSameMarket(item); + + // + return result; + } + + // + bool IsSameTime(XOHCL &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + time == item.time; + + // + return result; + } + + // + bool IsSameSymbol(XOHCL &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + // + bool IsSamePeriod(XOHCL &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + period == item.period; + + // + return result; + } + + // + bool IsSameMarket(XOHCL &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + IsSameSymbol(item) && + IsSamePeriod(item); + + // + 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 // + ); +} + +/** + * Remove Specified Item from a Collection ... + * + * @param item: Specified Item ... + * @param source: Specified Collection for Remove item from it ... + * + * @return ( bool ) + */ +bool Remove( + XOHCL &item, + XOHCL &source[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(source); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + source // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + source, + idx, + 1 // + ); + + // + return result; +} + +/** + * Remove Specified items from a Collection ... + * + * @param items: Specified Items to Remove ... + * @param sources: Sepcified Collection for Removing items from it ... + * + * @return ( int ) + */ +int Removes( + XOHCL &items[], + XOHCL &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int idx = -1; + has = false; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Detect Item Index in Collection ... + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + // Remove Detected Index from Collection ... + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + // + // Count Removed Items ... + result++; + } + } + } + + // + return result; +} + +/** + * Find Specified Item index in a Collection ... + * + * @param index: int, reference to Hold Index if Exists ... + * @param item: Specified item to Detect ... + * @param source: Collection to Search for item ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XOHCL &item, + XOHCL &source[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(source); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(source[i]); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Add Specified Item to Specified Collection, if not Exists ... + * + * @param item: Item to Add ... + * @param sources: Collection to Add item ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XOHCL &item, + XOHCL &sources[], + int maxAllowed = 0 // +) +{ + // + 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 // + ); + + // + // Handle Cleanup Collection + // if Max Reached ... + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +/** + * Get Oldest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetOldest( + XOHCL &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.time > source[i].time; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XOHCL &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.time < source[i].time; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetLowest( + XOHCL &source[], + ENUM_X_PRICE _priceType = X_PRICE_LOW // +) +{ + // + int result = -1; + + // + if (!IsXValid(_priceType)) + { + _priceType = X_PRICE_LOW; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + double iPrice = EMPTY_VALUE; + double selectedPrice = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + iPrice = source[i].GetPrice(_priceType); + selectedPrice = selected.GetPrice(_priceType); + + // + bool canSet = + !selected.IsValid() + ? true + : selectedPrice > iPrice; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param _priceType: Specified Price type ... + * + * @return ( int ) + */ +int GetHighest( + XOHCL &source[], + ENUM_X_PRICE _priceType = X_PRICE_HIGH // +) +{ + // + int result = -1; + + // + if (!IsXValid(_priceType)) + { + _priceType = X_PRICE_HIGH; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + double iPrice = EMPTY_VALUE; + double selectedPrice = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + iPrice = source[i].GetPrice(_priceType); + selectedPrice = selected.GetPrice(_priceType); + + // + bool canSet = + !selected.IsValid() + ? true + : selectedPrice < iPrice; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Nearest Directional Bar ... + * + * @param bar: XOHCL, reference to Specified Start Bar ... + * @param directionalBar: XOHCL, reference to hold Detected Bar ... + * @param forDir: ENUM_X_DIRECTION, Specified Which Directional Bar looking for ... + * @param loopback: int, Loopback Length ... + * + * @return ( bool ) + */ +bool GetDirectionalBar( + XOHCL &bar, + XOHCL &directionalBar, + ENUM_X_DIRECTION forDir, + int loopback = 1500 // +) +{ + // + bool result = false; + + // + // Prepare ... + directionalBar.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + int start = bar.Index() + 1; + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + directionalBar.Clean(); + result = bar.BarAt(i, directionalBar); + result = result && + directionalBar.GetDirection() == forDir; + if (result) + { + break; + } + + // + directionalBar.Clean(); + } + + // + result = directionalBar.IsValid() && + forDir == directionalBar.GetDirection(); + + // + // Cleanup Resources ... + if (!result) + { + directionalBar.Clean(); + } + + // + return result; +} + +/** + * Get Nearest Breaker Bar of Specified Bar's Price ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param breaker: XOHCL, reference to hold Detected Breaker Bar ... + * @param priceType: ENUM_X_PRICE, which price type of Bar to Check to Break ... + * @param breakType: ENUM_X_PRICE, which price of Breaker Bar must Breke price ... + * @param breakDir: ENUM_X_DIRECTION, Specified Break Direction ... + * @param loopback: int, Max Allowed Loopback to Detect Breaker Bar ... + * + * @return ( bool ) + */ +bool GetBreakerBar( + XOHCL &bar, + XOHCL &breaker, + ENUM_X_PRICE priceType, + ENUM_X_PRICE breakType, + ENUM_X_DIRECTION breakDir, + int loopback = 1500 // +) +{ + // + // PriceType: which Applied Price of Specified Bar must to Check for Break ... + + // + // BreakType: which Applied Price of breakerBar must Break price ... + + // + // BreakDir: + // ----------- + // Bullish: Price Must Break Applied Price from Down to Top ... + // Bearish: Price must Break Applied Price from Top to Down ... + + // + bool result = false; + + // + // Prepare ... + breaker.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(priceType) && + IsXValid(breakType) && + HasDirection(breakDir); + if (!result) + { + return result; + } + + // + double iPrice = EMPTY_VALUE; + bool isBullish = IsXBullish(breakDir); + double price = bar.GetPrice(priceType); + + // + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + breaker.Clean(); + iPrice = EMPTY_VALUE; + + // + // Initialize Indexed Bar ... + result = bar.BarAt(i, breaker); + if (!result) + { + breaker.Clean(); + break; + } + + // + // Check Breake ... + iPrice = breaker.GetPrice(breakType); + result = + isBullish + ? iPrice > price + : iPrice < price; + if (result) + { + break; + } + } + + // + result = breaker.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + breaker.Clean(); + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 new file mode 100644 index 0000000..5af5c4f --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 @@ -0,0 +1,3087 @@ +/////////////////////////////////////////////////////// +// +// 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 2025, 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-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +/** + * Model Specified Pivots Analysis ... + **/ +struct XPivotAnalysis +{ + // + // Props ... + string name; // Name ... + string symbol; // Symbol ... + datetime time; // Time ... + XPivot pivots[]; // Pivots ... + ENUM_TIMEFRAMES period; // Period ... + + // + // Linear Regression Parameters ... + double peakSlope; + double valeSlope; + double peakIntercept; + double valeIntercept; + + // + // Analysed Results ... + + // + // Directions ... + ENUM_X_DIRECTION dir; // Trending Direction ... + ENUM_X_DIRECTION peakDir; + ENUM_X_DIRECTION valeDir; + + // + // Predicted Values ... + double peakTo; + double valeTo; + double peakFrom; + double valeFrom; + + // + // Time Analysis ... + datetime toTime; + datetime fromTime; + + // + // Support and Resistances ... + double minorSupport; + double majorSupport; + double minorResistance; + double majorResistance; + + // + // Constructor ... + XPivotAnalysis() + { + Clean(); + } + + // + // Tools ... + + // + // Cleaners ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + time = NULL; + name = NULL; + symbol = NULL; + period = NULL; + SpecifiedClean(pivots); + + // + CleanAnalysis(); + CleanLinearRegressionParameters(); + + // + ZeroMemory(this); + } + + /** + * Clean Analysis Props ... + */ + void CleanAnalysis() + { + // + toTime = NULL; + fromTime = NULL; + peakTo = EMPTY_VALUE; + valeTo = EMPTY_VALUE; + peakFrom = EMPTY_VALUE; + valeFrom = EMPTY_VALUE; + dir = X_DIRECTION_NONE; + peakDir = X_DIRECTION_NONE; + valeDir = X_DIRECTION_NONE; + minorSupport = EMPTY_VALUE; + majorSupport = EMPTY_VALUE; + minorResistance = EMPTY_VALUE; + majorResistance = EMPTY_VALUE; + } + + /** + * Clean Linear Regression Parameters ... + */ + void CleanLinearRegressionParameters() + { + // + peakSlope = EMPTY_VALUE; + valeSlope = EMPTY_VALUE; + peakIntercept = EMPTY_VALUE; + valeIntercept = EMPTY_VALUE; + } + + // + // Initializer / Actions (s) ... + + /** + * Initialize Model ... + * + * @param _name: Name ... + * @param _symbol: Symbol ... + * @param _period: Period ... + * @param _pivots: Provided Pivots ... + * + * @return ( bool ) + */ + bool Init( + string _name, + string _symbol, + ENUM_TIMEFRAMES _period, + XPivot &_pivots[] // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + HasChild(_pivots) && + IsSpecifiedValid(_name) && + IsSpecifiedValid(_symbol) && + IsSpecifiedValid(_period); + if (!result) + { + // + Clean(); + return result; + } + + // + name = _name; + symbol = _symbol; + period = _period; + Copy( + _pivots, + pivots // + ); + time = TimeCurrent(); + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + // Do Calculations if Model is Valid ... + if (result) + { + Update(); + } + + // + return result; + } + + /** + * Fully Update Analysis based on Pivots ... + */ + void Update() + { + // + bool has = false; + + // + // Prepare ... + CleanAnalysis(); + CleanLinearRegressionParameters(); + + // + // Validate ... + has = IsValid() && + HasPivots(); + if (!has) + { + return; + } + + // + // Calculate Linear Regression Parameters ... + has = CalculateLinearRegressionParameters(); + if (!has) + { + return; + } + + // + // Analyse ... + has = Analyse(); + if (!has) + { + return; + } + } + + /** + * Fully Update Analysis based on Pivots ... + * + * @param _pivots: new Pivots Collection for Update ... + */ + void Update(XPivot &_pivots[]) + { + // + bool has = + IsValid() && + HasChild(_pivots); + if (!has) + { + return; + } + + // + SpecifiedClean(pivots); + Copy( + _pivots, + pivots // + ); + + // + Update(); + } + + /** + * Re Analyse Pivots ... + * + * @return ( bool ) + */ + bool Analyse() + { + // + bool result = false; + + // + // Prepare ... + CleanAnalysis(); + + // + // Validate ... + result = IsValid() && + HasPivots() && + HasLinearRegressionParameters(); + if (!result) + { + return result; + } + + // + // Do Analyse ... + + // + bool has = false; + + // + // Specified To and From Time ... + + // + // To Time ... + int toIDX = GetYoungest(pivots); + if (IsValidIndex(toIDX)) + { + // + toTime = pivots[toIDX].time; + toIDX = GetBarIndex( + symbol, + period, + toTime // + ); + } + + // + // From Time ... + int fromIDX = GetOldest(pivots); + if (IsValidIndex(fromIDX)) + { + // + fromTime = pivots[fromIDX].time; + fromIDX = GetBarIndex( + symbol, + period, + fromTime // + ); + } + + // + // Validate To From times ... + result = + IsValidIndex(toIDX) && + IsValidIndex(fromIDX) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (!result) + { + return result; + } + + // + // Predict Values ... + + // + // Peaks ... + + // + // Check Slope and Intercept Exists ... + has = NotEmpty(peakSlope) && + NotEmpty(peakIntercept); + if (has) + { + // + // To ... + peakTo = PredictValue( + peakSlope, + peakIntercept, + toIDX // + ); + + // + // From ... + peakFrom = PredictValue( + peakSlope, + peakIntercept, + fromIDX // + ); + } + + // + // Vales ... + + // + // Check Slope and Intercept Exists ... + has = NotEmpty(valeSlope) && + NotEmpty(valeIntercept); + if (has) + { + // + // To ... + valeTo = PredictValue( + valeSlope, + valeIntercept, + toIDX // + ); + + // + // From ... + valeFrom = PredictValue( + valeSlope, + valeIntercept, + fromIDX // + ); + } + + // + // Check Directions ... + + // + // Peak ... + has = IsPeakAnalysed(); + if (has) + { + // + peakDir = + peakFrom < peakTo + ? X_DIRECTION_BULLISH + : peakFrom > peakTo + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Vale ... + has = IsValeAnalysed(); + if (has) + { + // + valeDir = + valeFrom < valeTo + ? X_DIRECTION_BULLISH + : valeFrom > valeTo + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Check For Strong Type Trending ... + has = + IsPeakAnalysed() && + IsValeAnalysed() && + peakDir == valeDir; + if (has) + { + dir = peakDir; + } + + // + // Calculate Support and Resistances ... + + // + // Support ... + ExtractSupport( + minorSupport, + majorSupport, + pivots // + ); + + // + // Resistance ... + ExtractResistances( + minorResistance, + majorResistance, + pivots // + ); + + // + result = IsAnalysed(); + + // + // Cleanup Resources ... + + // + return result; + } + + /** + * Re Calculate Linear Regression Parameters ... + * + * @return ( bool ) + */ + bool CalculateLinearRegressionParameters() + { + // + bool result = false; + + // + // Prepare ... + CleanLinearRegressionParameters(); + + // + // Validate ... + result = IsValid() && + HasPivots(); + if (!result) + { + return result; + } + + // + // Make a Copy of Pivots ... + XPivot tmpPivots[]; + Copy( + pivots, + tmpPivots // + ); + + // + // Sort Pivots ... + Sort( + tmpPivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Do Calculations ... + + // + double yData[]; + double xData[]; + bool has = false; + + // + // Peaks ... + + // + XPivot peaks[]; + int peaksCount = ExtractPivots( + peaks, + tmpPivots, + X_PIVOT_TYPE_PEAK // + ); + has = IsValidSize(peaksCount); + if (has) + { + // + // Extract X and Y axis Data ... + ExtractPivotsData( + xData, + yData, + peaks // + ); + + // + // Calculating Slope and Intercept ... + has = ArraySize(xData) >= 2 && + ArraySize(yData) >= 2; + if (has) + { + // + CalculateSlopeAndIntercept( + peakSlope, + peakIntercept, + xData, + yData // + ); + } + } + + // + // Vales ... + + // + XPivot vales[]; + int valesCount = ExtractPivots( + vales, + tmpPivots, + X_PIVOT_TYPE_VALE // + ); + has = IsValidSize(valesCount); + if (has) + { + // + // Extract X and Y axis Data ... + ExtractPivotsData( + xData, + yData, + vales // + ); + + // + // Calculating Slope and Intercept ... + has = ArraySize(xData) >= 2 && + ArraySize(yData) >= 2; + if (has) + { + // + CalculateSlopeAndIntercept( + valeSlope, + valeIntercept, + xData, + yData // + ); + } + } + + // + // Validate Result ... + result = + IsValid() && + HasLinearRegressionParameters(); + + // + // Cleanup Resources ... + SpecifiedClean(yData); + SpecifiedClean(xData); + SpecifiedClean(peaks); + SpecifiedClean(vales); + SpecifiedClean(tmpPivots); + + // + return result; + } + + // + // Validator / Checker (s) ... + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + HasPivots() && + IsSpecifiedValid(time) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period); + + // + return result; + } + + /** + * Check Model has Pivots or not ... + * + * @return ( bool ) + */ + bool HasPivots() + { + // + bool result = false; + + // + result = HasChild(pivots); + + // + return result; + } + + /** + * Check Model is Analysed or not ... + * + * @return ( bool ) + */ + bool IsAnalysed() + { + // + bool result = false; + + // + result = + IsPeakAnalysed() || + IsValeAnalysed(); + + // + return result; + } + + /** + * Check Peak Analysed or not ... + * + * @return ( bool ) + */ + bool IsPeakAnalysed() + { + // + bool result = false; + + // + result = + IsValid() && + HasLinearRegressionParameters() && + ( + // + NotEmpty(peakTo) && + NotEmpty(peakFrom) && + // HasDirection(peakDir) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime) + // + ); + + // + return result; + } + + /** + * Check Vale Analysed or not ... + * + * @return ( bool ) + */ + bool IsValeAnalysed() + { + // + bool result = false; + + // + result = + IsValid() && + HasLinearRegressionParameters() && + ( + // + NotEmpty(valeTo) && + NotEmpty(valeFrom) && + // HasDirection(valeDir) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime) + // + ); + + // + return result; + } + + /** + * Check Models Linear Regression Parameters Calculated or not ... + * + * @return ( bool ) + */ + bool HasLinearRegressionParameters() + { + // + bool result = false; + + // + result = + (NotEmpty(peakSlope) && + NotEmpty(peakIntercept)) || + (NotEmpty(valeSlope) || + NotEmpty(valeIntercept)); + + // + return result; + } + + /** + * Check Analysis Has Trend or not ... + * + * @return ( bool ) + */ + bool HasTrend() + { + // + bool result = false; + + // + result = IsAnalysed() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Analysis Has Bullish Trend or not ... + * + * @return ( bool ) + */ + bool HasBullishTrend() + { + // + bool result = false; + + // + result = HasTrend() && + IsSpecifiedBullish(dir); + + // + return result; + } + + /** + * Check Analysis Has Bearish Trend or not ... + * + * @return ( bool ) + */ + bool HasBearishTrend() + { + // + bool result = false; + + // + result = HasTrend() && + IsSpecifiedBearish(dir); + + // + return result; + } + + /** + * Check Market Has Support ... + * + * @return ( bool ) + */ + bool HasSupport() + { + // + bool result = false; + + // + result = + IsValid() && + HasPivots() && + IsAnalysed() && + NotEmpty(minorSupport) && + NotEmpty(majorSupport); + + // + return result; + } + + /** + * Check Market Has Resistance ... + * + * @return ( bool ) + */ + bool HasResistance() + { + // + bool result = false; + + // + result = + IsValid() && + HasPivots() && + IsAnalysed() && + NotEmpty(minorResistance) && + NotEmpty(majorResistance); + + // + return result; + } + + // + // Pivots ... + + /** + * Extract all Peaks from Exists Pivots ... + * + * @param dest: a Collection refrence to Hold Extracted Pivots ... + * + * @return ( int ) + */ + int ExtractPeaks(XPivot &dest[]) + { + // + int result = -1; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Do Extraction ... + result = ExtractPivots( + dest, + pivots, + X_PIVOT_TYPE_PEAK // + ); + + // + return result; + } + + /** + * Extract all Vales from Exists Pivots ... + * + * @param dest: a Collection refrence to Hold Extracted Pivots ... + * + * @return ( int ) + */ + int ExtractVales(XPivot &dest[]) + { + // + int result = -1; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Do Extraction ... + result = ExtractPivots( + dest, + pivots, + X_PIVOT_TYPE_VALE // + ); + + // + return result; + } + + /** + * Sort Pivots ... + * + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + */ + void SortPivots( + ENUM_X_SORT_BY sortBy, + ENUM_X_DIRECTION sortDir // + ) + { + // + // Validate ... + bool has = IsValid() && + HasPivots(); + if (!has) + { + return; + } + + // + // Apply Sorting ... + Sort( + pivots, + sortBy, + sortDir // + ); + } + + // + // Boxing Tools ... + + /** + * Generate Support Box if Has Strong Supports ... + * + * @param box: a refrence XBoxZone to holds Generated result ... + * + * @return ( bool ) + */ + bool HasSupportBox(XBoxZone &box) + { + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Validate ... + result = + IsValid() && + IsAnalysed(); + if (!result) + { + return result; + } + + // + box.to = toTime; + box.symbol = symbol; + box.period = period; + box.from = fromTime; + + // + box.upper = minorSupport; + box.lower = majorSupport; + box.dir = X_DIRECTION_BULLISH; + box.type = GetTag() + "_Support"; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + /** + * Generate Resistance Box if Has Strong Resistance ... + * + * @param box: a refrence XBoxZone to holds Generated result ... + * + * @return ( bool ) + */ + bool HasResistanceBox(XBoxZone &box) + { + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Validate ... + result = + IsValid() && + IsAnalysed(); + if (!result) + { + return result; + } + + // + box.to = toTime; + box.symbol = symbol; + box.period = period; + box.from = fromTime; + + // + box.upper = majorResistance; + box.lower = minorResistance; + box.dir = X_DIRECTION_BEARISH; + box.type = GetTag() + "_Resistance"; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + // + // Detecting ... + + /** + * Check Two Model is Same or not ... + * + * @param item: Specified Model for Compare ... + * + * @return ( bool ) + */ + bool IsSameAs(XPivotAnalysis &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + IsSameMarketAs(item) && + name == item.name && + time == item.time; + + // + return result; + } + + /** + * Check Two Model Has Same Symbol or not ... + * + * @param item: Specified Model for Compare ... + * + * @return ( bool ) + */ + bool IsSameSymbolAs(XPivotAnalysis &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + /** + * Check Two Model Has Same Period or not ... + * + * @param item: Specified Model for Compare ... + * + * @return ( bool ) + */ + bool IsSamePeriodAs(XPivotAnalysis &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + period == item.period; + + // + return result; + } + + /** + * Check Two Model Has Same Symbol/Period or not ... + * + * @param item: Specified Model for Compare ... + * + * @return ( bool ) + */ + bool IsSameMarketAs(XPivotAnalysis &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + IsSameSymbolAs(item) && + IsSamePeriodAs(item); + + // + return result; + } + + // + // Logging ... + + /** + * Extract Specified Token of Struct ... + * + * @return ( string ) + */ + string GetTag() + { + return name + GetToken(this); + } + + /** + * Represent an String Unique Identifier for Chart Objects ... + * + * @return ( string ) + */ + string GetObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period); + + // + return result; + } + + /** + * Represent an String Unique Identifier for Upper Trend Chart Objects ... + * + * @return ( string ) + */ + string GetUpperObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_UPPER"; + + // + return result; + } + + /** + * Represent an String Unique Identifier for Lower Trend Chart Objects ... + * + * @return ( string ) + */ + string GetLowerObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_LOWER"; + + // + return result; + } + + /** + * Represent an String Unique Identifier for Support Box Chart Objects ... + * + * @return ( string ) + */ + string GetSupportBoxObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_SUPPORT"; + + // + return result; + } + + /** + * Represent an String Unique Identifier for Resistance BOX Chart Objects ... + * + * @return ( string ) + */ + string GetResistanceBoxObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_RESISTANCE"; + + // + return result; + } + + /** + * Represent as String ... + * + * @param spacer: string, How to Represent Spaces ... + * + * @return ( string ) + */ + string GetMessage(string spacer = NULL) + { + // + string result = ""; + + // + // Normalize Spacer ... + if (!IsSpecifiedValid(spacer)) + { + spacer = " "; + } + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + result = + "==========================" + spacer + + GetTag() + ":" + spacer + + "==========================" + spacer + + "Symbol: " + symbol + spacer + + "Period: " + ToXString(period) + spacer + + (!HasTrend() + ? "" + : "Direction: " + ToXString(dir) + spacer) + + "Time: " + ToXString(time) + spacer; + + // + return result; + } + + // +}; + +/** + * a Model to Describe Specified Bar Pattern's Analysis ... + **/ +struct XPatternAnalysis +{ + // + // Props ... + XOHCL bar; // Specified Bar ... + XBoxZone ob; // OrderBlock if Exists ... + XBoxZone fvg; // Fair Value Gap if Exists ... + datetime time; // Analysis Time ... + XOHCL flagSwing; // Flag Patterns Swing Bar if Exists ... + XBoxZone support; // Bar's Support if Exists ... + XBoxZone resistance; // Bar's Resistance if Exists ... + ENUM_X_BAR_PATTERN patterns[]; // All Bars Exists Patterns ... + ENUM_X_DIRECTION patternsDir[]; // Each Exists Patterns Directions ... + + // + // Constructor ... + XPatternAnalysis() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + ob.Clean(); + bar.Clean(); + fvg.Clean(); + time = NULL; + support.Clean(); + XClean(patterns); + flagSwing.Clean(); + resistance.Clean(); + XClean(patternsDir); + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = bar.IsValid() && + IsXValid(time); + + // + return result; + } + + // + // Pattern Actions ... + + /** + * Count Directional Patterns ... + * + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( int ) + */ + int Count( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Validate ... + bool has = IsValid() && + HasChild(patternsDir); + if (!has) + { + return result; + } + + // + int count = ArraySize(patternsDir); + if (!HasDirection(forDir)) + { + // + result = count; + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + has = forDir == patternsDir[i]; + if (has) + { + result++; + } + } + + // + return result; + } + + // + // Detectors ... + + bool IsHigh() + { + // + bool result = false; + + // + result = HasPattern(X_BAR_PATTERN_HIGH); + + // + return result; + } + + bool IsLow() + { + // + bool result = false; + + // + result = HasPattern(X_BAR_PATTERN_LOW); + + // + return result; + } + + bool IsSupport() + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_SUPPORT // + ); + + // + return result; + } + + bool IsResistance() + { + // + bool result = false; + + // + result = HasPattern(X_BAR_PATTERN_RESISTANCE); + + // + return result; + } + + bool IsMomentum( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_MOMENTUM, + forDir // + ); + + // + return result; + } + + bool IsEngulfed( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_ENGULFED, + forDir // + ); + + // + return result; + } + + bool IsTrueGaped( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_TRUE_GAPED, + forDir // + ); + + // + return result; + } + + bool IsPinned( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_PINNED, + forDir // + ); + + // + return result; + } + + bool IsStar( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_STAR, + forDir // + ); + + // + return result; + } + + bool IsPiercing( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_PIERCING, + forDir // + ); + + // + return result; + } + + bool IsRising( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_RISING, + forDir // + ); + + // + return result; + } + + bool IsFlag( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_FLAG, + forDir // + ); + + // + return result; + } + + bool IsSignalKey( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_SIGNALKEY, + forDir // + ); + + // + return result; + } + + bool IsOB( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_OB, + forDir // + ); + + // + return result; + } + + bool IsFVG( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_FVG, + forDir // + ); + + // + return result; + } + + // + // Getters ... + + bool GetLow( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_LOW; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BULLISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetHigh( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_HIGH; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BEARISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetSupport( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_SUPPORT; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BULLISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetResistance( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_RESISTANCE; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BEARISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetOB( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_OB; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetFVG( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_FVG; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetMomentum( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_MOMENTUM; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetEngulfed( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_ENGULFED; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetPinned( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_PINNED; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetTrueGaped( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_TRUE_GAPED; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetStar( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_STAR; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetFlag( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_FLAG; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetRising( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_RISING; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetPiercing( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_PIERCING; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetSignalKey( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_SIGNALKEY; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + // + // Common Tools ... + + /** + * Add Specified Patterns to Model ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * @param patternDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + */ + void AddPattern( + ENUM_X_BAR_PATTERN pattern, + ENUM_X_DIRECTION patternDir // + ) + { + // + bool has = IsXValid(pattern) && + HasDirection(patternDir); + if (!has) + { + return; + } + + // + Add( + pattern, + patterns // + ); + + // + Add( + patternDir, + patternsDir // + ); + } + + /** + * Check Model Has Specified Pattern or not ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * @param patternDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * + * @return ( bool ) + */ + bool HasPattern( + ENUM_X_BAR_PATTERN pattern, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = Contains( + pattern, + patterns // + ); + if (!result) + { + return result; + } + + // + if (HasDirection(forDir)) + { + // + int idx = FindIndex( + pattern, + patterns // + ); + result = + IsValidIndex(idx) && + forDir == patternsDir[idx]; + } + + // + return result; + } + + /** + * Get Specified Pattern if Exists ... + * + * @param _bar: XOHCL, Patterns Bar ... + * @param _pivot: XPivot, Patterns Pivot ... + * @param _zone: XBoxZone, Patterns Box ... + * @param _pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * @param _patternDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * @param _peakPriceType: ENUM_X_PRICE, Specified Peak Price Type ... + * @param _valePriceType: ENUM_X_PRICE, Specified Vale Price Type ... + * @param _toTime: datetime, Specified Time to Update Pivot and Zones ... + * + * @return ( bool ) + */ + bool GetPattern( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_BAR_PATTERN _pattern, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW, + datetime _toTime = NULL // + ) + { + // + bool result = false; + + // + // Prepare ... + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Normalize ... + if (!IsXValid(_peakPriceType)) + { + _peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(_valePriceType)) + { + _valePriceType = X_PRICE_LOW; + } + _toTime = NormalizeTime(_toTime); + + // + // Validate ... + result = IsValid() && + HasChild(patterns) && + IsXValid(_peakPriceType) && + IsXValid(_valePriceType) && + HasPattern(_pattern, _patternDir); + if (!result) + { + return result; + } + + // + // Find Pattern Index ... + int index = FindIndex(_pattern, patterns); + result = IsValidIndex(index); + if (!result) + { + return result; + } + + // + // Fill Common Patterns Data ... + _bar = bar; + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + result = result && + ToBox( + _bar, + _zone, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + if (result) + { + _zone.to = _toTime; + } + + // + // Use Custom Data if Pattern Staisfied ... + if (result) + { + // + // OB ... + if (_pattern == X_BAR_PATTERN_OB) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = ob.IsValid() && + ob.dir == _patternDir; + if (result) + { + // + _zone = ob; + result = _zone.FromBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + // + // FVG ... + else if (_pattern == X_BAR_PATTERN_FVG) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = fvg.IsValid() && + fvg.dir == _patternDir; + if (result) + { + // + _zone = fvg; + result = _zone.FromBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + // + // Support ... + else if (_pattern == X_BAR_PATTERN_SUPPORT) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = support.IsValid(); + if (result) + { + // + _zone = support; + result = _zone.AtBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + // + // Resistance ... + else if (_pattern == X_BAR_PATTERN_RESISTANCE) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = resistance.IsValid(); + if (result) + { + // + _zone = resistance; + result = _zone.AtBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + } + + // + // Cleanup Resources ... + if (!result) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + } + + // + return result; + } + + /** + * Extract All Exists Patterns Pivots ... + * + * @param dest: XPivot, collection reference to holds Extracted Patterns ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction of Extractions ... + * + * @return ( int ) + */ + int GetPatterns( + XPivot &dest[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = IsValid() && + HasChild(patterns); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL iBar; + XPivot iPivot; + XBoxZone iZone; + int count = ArraySize(patterns); + for (int i = 0; i < count; i++) + { + // + has = GetPattern(iBar, iPivot, iZone, patterns[i], forDir); + if (has) + { + AddIfNotExists(iPivot, dest); + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iPivot.Clean(); + + // + return result; + } + + /** + * Extract All Exists Patterns Pivots ... + * + * @param dest: XBoxZone, collection reference to holds Extracted Patterns ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction of Extractions ... + * + * @return ( int ) + */ + int GetPatterns( + XBoxZone &dest[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = IsValid() && + HasChild(patterns); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL iBar; + XPivot iPivot; + XBoxZone iZone; + int count = ArraySize(patterns); + for (int i = 0; i < count; i++) + { + // + has = GetPattern(iBar, iPivot, iZone, patterns[i], forDir); + if (has) + { + AddIfNotExists(iZone, dest); + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iPivot.Clean(); + + // + return result; + } + + /** + * Extract All Exists Patterns Pivots ... + * + * @param dest: XPivot, collection reference to holds Extracted Patterns ... + * @param zones: XBoxZone, collection reference to holds Extracted Patterns ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction of Extractions ... + * + * @return ( int ) + */ + int GetPatterns( + XPivot &dest[], + XBoxZone &zones[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + XClean(zones); + + // + // Validate ... + bool has = IsValid() && + HasChild(patterns); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL iBar; + XPivot iPivot; + XBoxZone iZone; + int count = ArraySize(patterns); + for (int i = 0; i < count; i++) + { + // + has = GetPattern(iBar, iPivot, iZone, patterns[i], forDir); + if (has) + { + // + AddIfNotExists(iPivot, dest); + AddIfNotExists(iZone, zones); + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iPivot.Clean(); + + // + return result; + } + + // +}; + +struct XPatternAnalysisConfig +{ + // + // Props ... + + // + // PV ... + int pvValidationLength; + ENUM_X_PRICE peakPriceType; + ENUM_X_PRICE valePriceType; + + // + // Momentum ... + int momentumBarValidationLength; + double momentumBarApprovedMultiplier; + + // + // TrueGap ... + double trueGapApprovedStrength; + + // + // Pin ... + double pinBarShadowApprovedMultiplier; + double pinBarRangeMultiplier; + bool pinBarForceDirection; + + // + // Flag ... + int flagPatternPullbackLength; + + // + // FVG ... + bool fvgForceType; + + // + // OB ... + bool obForceTwoBar; + + // + // Support and Resistance ... + int supportAndResistanceValidationLength; + int supportAndResistanceLoopbackLength; + + // + ENUM_X_DIRECTION allowedDirs[]; + ENUM_X_BAR_PATTERN allowedPatterns[]; + + // + // Constructor ... + XPatternAnalysisConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + // PV ... + pvValidationLength = 0; + peakPriceType = X_PRICE_NONE; + valePriceType = X_PRICE_NONE; + + // + // Momentum ... + momentumBarValidationLength = 0; + momentumBarApprovedMultiplier = 0; + + // + // TrueGap ... + trueGapApprovedStrength = 0; + + // + // Pin ... + pinBarShadowApprovedMultiplier = 0; + pinBarRangeMultiplier = 0; + pinBarForceDirection = false; + + // + // Flag ... + flagPatternPullbackLength = 0; + + // + // FVG ... + fvgForceType = false; + + // + // OB ... + obForceTwoBar = false; + + // + // Support and Resistance ... + supportAndResistanceValidationLength = 0; + supportAndResistanceLoopbackLength = 0; + + // + XClean(allowedDirs); + XClean(allowedPatterns); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // PV ... + pvValidationLength = 5; + peakPriceType = X_PRICE_HIGH; + valePriceType = X_PRICE_LOW; + + // + // Momentum ... + momentumBarValidationLength = 3; + momentumBarApprovedMultiplier = 3; + + // + // TrueGap ... + trueGapApprovedStrength = 1; + + // + // Pin ... + pinBarShadowApprovedMultiplier = 3; + pinBarRangeMultiplier = 4; + pinBarForceDirection = false; + + // + // Flag ... + flagPatternPullbackLength = 3; + + // + // FVG ... + fvgForceType = false; + + // + // OB ... + obForceTwoBar = false; + + // + // Support and Resistance ... + supportAndResistanceValidationLength = 21; + supportAndResistanceLoopbackLength = 50; + } + + // + // Permissions ... + + /** + * Check Specified Patterns Detection is Allowed or not ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern to Detect ... + * @param patternDir: ENUM_X_DIRECTION, which Pattern Direction to Detect ... + * + * @return ( bool ) + */ + bool CanDetect( + ENUM_X_BAR_PATTERN pattern, + ENUM_X_DIRECTION patternDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + // Validate Pattern and + // Check Pattern Exists ... + result = IsXValid(pattern) && + HasChild(allowedPatterns) && + Contains(pattern, allowedPatterns); + if (!result) + { + return result; + } + + // + // Now Check Direction ... + int index = FindIndex(pattern, allowedPatterns); + result = IsValidIndex(index) && + HasChild(allowedDirs) && + (!HasDirection(patternDir) + ? !HasDirection(allowedDirs[index]) + : (!HasDirection(allowedDirs[index]) || + patternDir == allowedDirs[index])); + + // + return result; + } + + // + // Collection Manipulations ... + + /** + * Remove all Allowed Patterns and Directions ... + */ + void CleanPatterns() + { + // + XClean(allowedDirs); + XClean(allowedPatterns); + } + + /** + * Full Detect Patterns ... + * + * @param forDir: ENUM_X_DIRECTION, which Pattern Direction to Detect ... + */ + void FullPattern( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int count = GetAllBarPatters(allowedPatterns); + for (int i = 0; i < count; i++) + { + // + Add( + forDir, + allowedDirs // + ); + } + } + + /** + * Add Specified Pattern to Detecte ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern to Detect ... + * @param patternDir: ENUM_X_DIRECTION, which Pattern Direction to Detect ... + */ + void AddPattern( + ENUM_X_BAR_PATTERN pattern, + ENUM_X_DIRECTION patternDir = X_DIRECTION_NONE // + ) + { + // + bool has = IsXValid(pattern); + if (!has) + { + return; + } + + // + Add( + pattern, + allowedPatterns // + ); + + // + Add( + patternDir, + allowedDirs // + ); + } + + // +}; + +// +// Anaysis Draw Config Models ... + +struct XPivotAnalysisDrawConfig +{ + // + // Props ... + + // + // Drawing Flags ... + bool drawSupport; + bool drawResistance; + + // + bool drawPeakTrend; + bool drawValeTrend; + bool rayLeftTrends; + bool rayRightTrends; + + // + bool drawPivots; + + // + // Drawing Configs ... + XPOIDrawConfig drawConfig; + + // + // Constructor ... + XPivotAnalysisDrawConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Drawing Flags ... + + // + drawPivots = false; + drawSupport = false; + drawPeakTrend = false; + drawValeTrend = false; + rayLeftTrends = false; + rayRightTrends = false; + drawResistance = false; + + // + // Drawing Configs ... + drawConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Drawing Flags ... + + // + drawPivots = false; + drawSupport = true; + drawPeakTrend = false; + drawValeTrend = false; + rayLeftTrends = true; + rayRightTrends = true; + drawResistance = true; + + // + // Drawing Configs ... + drawConfig.Default(); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + drawPivots = false; + drawSupport = false; + drawPeakTrend = false; + drawValeTrend = false; + drawResistance = false; + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + drawPivots = true; + drawSupport = true; + drawPeakTrend = true; + drawValeTrend = true; + drawResistance = true; + } + + // +}; + +struct XPatternAnalysisDrawConfig +{ + // + // Props ... + + // + // Patterns ... + + // + ENUM_X_BAR_PATTERN allowedDraws[]; // Allowed Draw Patterns + ENUM_X_BAR_PATTERN allowedDrawZones[]; // Allowed Draw Pattern Zones + ENUM_X_BAR_PATTERN allowedDrawPivots[]; // Allowed Draw Pattern Pivots + + // + XPOIDrawConfig drawConfig; + + // + // Constructor ... + XPatternAnalysisDrawConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + // Drawing Configs ... + drawConfig.Clean(); + + // + XClean(allowedDraws); + XClean(allowedDrawZones); + XClean(allowedDrawPivots); + } + + /** + * Default Drawing Config ... + */ + void Default() + { + // + // Drawing Configs ... + drawConfig.Default(); + + // + Full(); + + // + // Remove Unused From Zones ... + Remove(X_BAR_PATTERN_PINNED, allowedDrawZones); + Remove(X_BAR_PATTERN_MOMENTUM, allowedDrawZones); + Remove(X_BAR_PATTERN_ENGULFED, allowedDrawZones); + Remove(X_BAR_PATTERN_TRUE_GAPED, allowedDrawZones); + + // + // Remove Unused From Pivots ... + Remove(X_BAR_PATTERN_OB, allowedDrawPivots); + Remove(X_BAR_PATTERN_FVG, allowedDrawPivots); + Remove(X_BAR_PATTERN_SUPPORT, allowedDrawPivots); + Remove(X_BAR_PATTERN_RESISTANCE, allowedDrawPivots); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + XClean(allowedDraws); + XClean(allowedDrawZones); + XClean(allowedDrawPivots); + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + GetAllBarPatters(allowedDraws); + GetAllBarPatters(allowedDrawZones); + GetAllBarPatters(allowedDrawPivots); + } + + // + // Checkers ... + + /** + * Check Can Draw Specified Pattern ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * + * @return ( bool ) + */ + bool CanDraw(ENUM_X_BAR_PATTERN pattern) + { + // + bool result = false; + + // + result = HasChild(allowedDraws) && + Contains(pattern, allowedDraws); + + // + return result; + } + + /** + * Check Can Draw Specified Pattern's Zone ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * + * @return ( bool ) + */ + bool CanDrawZone(ENUM_X_BAR_PATTERN pattern) + { + // + bool result = false; + + // + result = + CanDraw(pattern) && + HasChild(allowedDrawZones) && + Contains(pattern, allowedDrawZones); + + // + return result; + } + + /** + * Check Can Draw Specified Pattern's Pivot ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * + * @return ( bool ) + */ + bool CanDrawPivot(ENUM_X_BAR_PATTERN pattern) + { + // + bool result = false; + + // + result = + CanDraw(pattern) && + HasChild(allowedDrawPivots) && + Contains(pattern, allowedDrawPivots); + + // + return result; + } +}; + +// +// Extensions ... + +bool FindByTime( + int &index, + datetime time, + XPatternAnalysis &source[] // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + result = IsXValid(time) && + HasChild(source); + if (!result) + { + return result; + } + + // + // Do ... + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + result = source[i].bar.time == time; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14041018/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..d17d487 --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -0,0 +1,6554 @@ +/////////////////////////////////////////////////////// +// +// 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-ohcl.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Extensions ... +//+------------------------------------------------------------------+ +//| Oldest Detection | +//+------------------------------------------------------------------+ +/** + * Get Oldest Index of Specified Collection ... + * + * @param source: Specified 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++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > source[i].from; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Oldest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( int ) + */ +int GetOldestByDir( + XBoxZone &source[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + (!HasDirection(forDir) + ? true + : forDir == source[i].dir) && + (!selected.IsValid() + ? true + : selected.from > source[i].from); + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Oldest Index of Specified Collection ... + * + * @param bar: XOHCL, Specified Bar ... + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetOldestByBar( + 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++) + { + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]); + if (!isBoxValidForBar) + { + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > source[i].from; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Oldest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... + * + * @return ( int ) + */ +int GetOldest( + XPivot &source[], + ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(source)) + { + return result; + } + + // + bool has = false; + XPivot iPoint; + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + // Passed Type ... + has = !IsXValid(type) + ? true + : type == source[i].type; + + // + // Check Can Assign ... + has = + has && + (!iPoint.IsValid() || + (iPoint.IsValid() && + source[i].GetAge() > iPoint.GetAge())); + if (has) + { + // + result = i; + iPoint = source[i]; + } + } + + // + // Validate Result ... + has = + iPoint.IsValid() && + IsValidIndex(result); + if (!has) + { + // + result = -1; + iPoint.Clean(); + return result; + } + + // + iPoint.Clean(); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Youngest Detection | +//+------------------------------------------------------------------+ +/** + * Get Youngest Index of Specified Collection ... + * + * @param source: Specified 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++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < source[i].from; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( int ) + */ +int GetYoungestByDir( + XBoxZone &source[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + (!HasDirection(forDir) + ? true + : forDir == source[i].dir) && + (!selected.IsValid() + ? true + : selected.from < source[i].from); + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index of Specified Collection ... + * + * @param bar: XOHCL, Specified Bar ... + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetYoungestByBar( + 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++) + { + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]); + if (!isBoxValidForBar) + { + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < source[i].from; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... + * + * @return ( int ) + */ +int GetYoungest( + XPivot &source[], + ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(source)) + { + return result; + } + + // + bool has = false; + XPivot iPoint; + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + // Passed Type ... + has = !IsXValid(type) + ? true + : type == source[i].type; + + // + // Check Can Assign ... + has = + has && + (!iPoint.IsValid() || + (iPoint.IsValid() && + source[i].GetAge() < iPoint.GetAge())); + if (has) + { + // + result = i; + iPoint = source[i]; + } + } + + // + // Validate Result ... + has = + iPoint.IsValid() && + IsValidIndex(result); + if (!has) + { + // + result = -1; + iPoint.Clean(); + return result; + } + + // + iPoint.Clean(); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Highest Detection | +//+------------------------------------------------------------------+ +/** + * Get Highest Index of Specified Collection ... + * + * @param source: Specified 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++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < source[i].upper; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( int ) + */ +int GetHighestByDir( + XBoxZone &source[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + (!HasDirection(forDir) + ? true + : forDir == source[i].dir) && + (!selected.IsValid() + ? true + : selected.upper < source[i].upper); + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index of Specified Collection ... + * + * @param bar: XOHCL, Specified Bar ... + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetHighestByBar( + 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 Highest Bar Price Index of Specified Collection ... + * + * @param source: reference collection, Provides Data Source ... + * + * @return ( int ) + */ +int GetHighestBarPrice( + XOHCL &source[], + ENUM_X_PRICE priceType // +) +{ + // + int result = -1; + + // + // Validate ... + bool has = HasChild(source) && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + double price = EMPTY_VALUE; + double selected = EMPTY_VALUE; + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + price = source[i].GetPrice(priceType); + has = !NotEmptyZero(selected) + ? true + : price > selected; + if (has) + { + // + result = i; + selected = price; + } + } + + // + return result; +} + +/** + * Get Highest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... + * + * @return ( int ) + */ +int GetHighest( + XPivot &source[], + ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(source)) + { + return result; + } + + // + bool has = false; + XPivot iPoint; + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + // Passed Type ... + has = !IsXValid(type) + ? true + : type == source[i].type; + + // + // Check Can Assign ... + has = + has && + (!iPoint.IsValid() || + (iPoint.IsValid() && + source[i].value > iPoint.value)); + if (has) + { + // + result = i; + iPoint = source[i]; + } + } + + // + // Validate Result ... + has = + iPoint.IsValid() && + IsValidIndex(result); + if (!has) + { + // + result = -1; + iPoint.Clean(); + return result; + } + + // + iPoint.Clean(); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Loest Detection | +//+------------------------------------------------------------------+ +/** + * Get Lowest Index of Specified Collection ... + * + * @param source: Specified 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; +} + +/** + * Get Lowest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( int ) + */ +int GetLowestByDir( + XBoxZone &source[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + 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 = + (!HasDirection(forDir) + ? true + : forDir == source[i].dir) && + (!selected.IsValid() + ? true + : selected.lower > iBox.lower); + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index of Specified Collection ... + * + * @param bar: XOHCL, Specified Bar ... + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetLowestByBar( + 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 Lowest Bar Price Index of Specified Collection ... + * + * @param source: reference collection, Provides Data Source ... + * + * @return ( int ) + */ +int GetLowestBarPrice( + XOHCL &source[], + ENUM_X_PRICE priceType // +) +{ + // + int result = -1; + + // + // Validate ... + bool has = HasChild(source) && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + double price = EMPTY_VALUE; + double selected = EMPTY_VALUE; + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + price = source[i].GetPrice(priceType); + has = !NotEmptyZero(selected) + ? true + : price < selected; + if (has) + { + // + result = i; + selected = price; + } + } + + // + return result; +} + +/** + * Get Lowest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... + * + * @return ( int ) + */ +int GetLowest( + XPivot &items[], + ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(items)) + { + return result; + } + + // + bool has = false; + XPivot iPoint; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Passed Type ... + has = !IsXValid(type) + ? true + : type == items[i].type; + + // + // Check Can Assign ... + has = + has && + (!iPoint.IsValid() || + (iPoint.IsValid() && + items[i].value < iPoint.value)); + if (has) + { + // + result = i; + iPoint = items[i]; + } + } + + // + // Validate Result ... + has = + iPoint.IsValid() && + IsValidIndex(result); + if (!has) + { + // + result = -1; + iPoint.Clean(); + return result; + } + + // + iPoint.Clean(); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Box | +//+------------------------------------------------------------------+ +/** + * Extract all items which appears Before Specified Time ... + * + * @param _time: Specified Time ... + * @param dest: refrence collection to hold result ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetBeforeItems( + datetime _time, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + int count = ArraySize(source); + bool has = HasChild(source) && + IsSpecifiedValid(_time); + if (!has) + { + return result; + } + + // + // Loop through Items ... + for (int i = 0; i < count; i++) + { + // + has = source[i].from < _time; + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all items which appears After Specified Time ... + * + * @param _time: Specified Time ... + * @param dest: refrence collection to hold result ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetAfterItems( + datetime _time, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + int count = ArraySize(source); + bool has = HasChild(source) && + IsSpecifiedValid(_time); + if (!has) + { + return result; + } + + // + // Loop through Items ... + for (int i = 0; i < count; i++) + { + // + has = source[i].from > _time; + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all items which appears Above Specified Value ... + * + * @param _value: Specified Value ... + * @param dest: refrence collection to hold result ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetAboveItems( + double _value, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + int count = ArraySize(source); + bool has = HasChild(source) && + NotEmptyZero(_value); + if (!has) + { + return result; + } + + // + // Loop through Items ... + for (int i = 0; i < count; i++) + { + // + has = source[i].lower > _value; + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all items which appears Below Specified Value ... + * + * @param _value: Specified Value ... + * @param dest: refrence collection to hold result ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetBelowItems( + double _value, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + int count = ArraySize(source); + bool has = HasChild(source) && + NotEmptyZero(_value); + if (!has) + { + return result; + } + + // + // Loop through Items ... + for (int i = 0; i < count; i++) + { + // + has = source[i].upper < _value; + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Get Oldest Item Index of all items which appears Before Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetOldestBefore( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBeforeItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetOldest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Oldest Item Index of all items which appears After Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetOldestAfter( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAfterItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetOldest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Oldest Item Index of all items which appears Above Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetOldestAbove( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAboveItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetOldest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Oldest Item Index of all items which appears Below Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetOldestBelow( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBelowItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetOldest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Youngest Item Index of all items which appears Before Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetYoungestBefore( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBeforeItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetYoungest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Youngest Item Index of all items which appears After Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetYoungestAfter( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAfterItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetYoungest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Youngest Item Index of all items which appears Above Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetYoungestAbove( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAboveItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetYoungest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Youngest Item Index of all items which appears Below Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetYoungestBelow( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBelowItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetYoungest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Highest Item Index of all items which appears Before Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetHighestBefore( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBeforeItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetHighest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Highest Item Index of all items which appears After Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetHighestAfter( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAfterItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetHighest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Highest Item Index of all items which appears Above Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetHighestAbove( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAboveItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetHighest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Highest Item Index of all items which appears Below Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetHighestBelow( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBelowItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetHighest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Lowest Item Index of all items which appears Before Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetLowestBefore( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBeforeItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetLowest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Lowest Item Index of all items which appears After Specified Value ... + * + * @param _time: Specified Time ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetLowestAfter( + datetime _time, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAfterItems( + _time, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetLowest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Lowest Item Index of all items which appears Above Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetLowestAbove( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetAboveItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetLowest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Get Lowest Item Index of all items which appears Below Specified Value ... + * + * @param _value: Specified Value ... + * @param source: refrence collection to provides data source ... + * + * @return ( int ) + */ +int GetLowestBelow( + double _value, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + XBoxZone tmps[]; + int tmpsCount = GetBelowItems( + _value, + tmps, // Dest ... + source // Source ... + ); + bool has = IsValidSize(tmpsCount); + int idx = GetLowest(tmps); + has = + has && + IsValidIndex(idx) && + FindIndex( + result, + tmps[idx], + source // + ); + SpecifiedClean(tmps); + + // + return result; +} + +/** + * Validate an Item Strength ... + * + * @param item: Specified Item for Validating ... + * @param minAllowedStrength: int, Minimum required Strength in Point ... + * + * @return ( bool ) + */ +bool ValidateStrength( + XBoxZone &item, + int minAllowedStrength = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + minAllowedStrength = NormalizeInt(minAllowedStrength, 0); + + // + // Validate ... + result = item.IsValid(); + if (!result) + { + return result; + } + + // + // If doent provide Specified Strength Validate Zone ... + result = minAllowedStrength <= 0; + if (result) + { + return result; + } + + // + double points = GetPoints(item.symbol); + double requiredStrength = minAllowedStrength * points; + double itemStrength = item.upper - item.lower; + + // + result = + itemStrength > 0 && + requiredStrength > 0 && + itemStrength > requiredStrength; + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Sort | +//+------------------------------------------------------------------+ + +/** + * Allowed Sort Param ... + **/ +enum ENUM_X_SORT_BY +{ + X_SORT_BY_NONE = 0, // None + X_SORT_BY_DATE = 1, // by Date + X_SORT_BY_VALUE = 2, // by Date +}; + +/** + * Check Specified Sort By Validation ... + * + * @param value: ENUM_X_SORT_BY, value to Validate ... + * + * @return ( bool ) + */ +bool IsXValid(ENUM_X_SORT_BY value) +{ + return value != X_SORT_BY_NONE; +} + +/** + * Select Specified Index of a Collection by Sort Params ... + * + * @param source: Collection for Search ... + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + * + * @return ( int ) + */ +template +int SelectItemForSorting( + T &source[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(source) || + !IsXValid(sortBy) || + !HasDirection(sortDir)) + { + return result; + } + + // + // Sort By Date ... + if (sortBy == X_SORT_BY_DATE) + { + // + // Select Based on Sorting Direction ... + + // + // form Oldest to Youngest ... + if (sortDir == X_DIRECTION_BULLISH) + { + result = GetOldest(source); + } + // + // form Youngest to Oldest ... + else if (sortDir == X_DIRECTION_BEARISH) + { + result = GetYoungest(source); + } + // + // Not Valid ... + else + { + result = -1; + } + } + // + // Sort By Value ... + else if (sortBy == X_SORT_BY_VALUE) + { + // + // form Lowst to Highest ... + if (sortDir == X_DIRECTION_BULLISH) + { + result = GetLowest(source); + } + // + // form Highest to Lowest ... + else if (sortDir == X_DIRECTION_BEARISH) + { + result = GetHighest(source); + } + // + // Not Valid ... + else + { + result = -1; + } + } + // + // Not Valid ... + else + { + result = -1; + } + + // + return result; +} + +/** + * Select Specified Index of a Collection by Sort Params ... + * + * @param source: Collection for Search ... + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + * + * @return ( int ) + */ +int SelectBarForSorting( + XOHCL &source[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, + ENUM_X_PRICE priceType = X_PRICE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(source) || + !IsXValid(sortBy) || + !HasDirection(sortDir)) + { + return result; + } + + // + // Sort By Date ... + if (sortBy == X_SORT_BY_DATE) + { + // + // Select Based on Sorting Direction ... + + // + // form Oldest to Youngest ... + if (sortDir == X_DIRECTION_BULLISH) + { + result = GetOldest(source); + } + // + // form Youngest to Oldest ... + else if (sortDir == X_DIRECTION_BEARISH) + { + result = GetYoungest(source); + } + // + // Not Valid ... + else + { + result = -1; + } + } + // + // Sort By Value ... + else if (sortBy == X_SORT_BY_VALUE) + { + // + // form Lowst to Highest ... + if (sortDir == X_DIRECTION_BULLISH) + { + result = GetLowest(source, priceType); + } + // + // form Highest to Lowest ... + else if (sortDir == X_DIRECTION_BEARISH) + { + result = GetHighest(source, priceType); + } + // + // Not Valid ... + else + { + result = -1; + } + } + // + // Not Valid ... + else + { + result = -1; + } + + // + return result; +} + +/** + * Apply Sort on Specified Collection ... + * + * @param source: Collection Reference to Sort ... + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + * @param maxAllowed: int, Max Allowed Collection Size ... + */ +template +void Sort( + T &source[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH, + int maxAllowed = 0 // +) +{ + // + int idx = -1; + bool has = false; + + // + // Validate ... + has = + IsXValid(sortBy) && + HasChild(source) && + HasDirection(sortDir); + if (!has) + { + return; + } + + // + // Copy source for Manipulating ... + T tmps[]; + Copy( + source, + tmps // + ); + + // + // Clean Source Collection for Adding Sorted Items ... + Clean(source); + + // + // Loop Through Temp Collection Has Child ... + while (HasChild(tmps)) + { + // + // Select Based on Sorting Parameter ... + idx = SelectItemForSorting( + tmps, + sortBy, + sortDir // + ); + + // + // Validate Detected Index ... + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + // Add Detected Indexed Item to Source ... + AddRef( + tmps[idx], + source // + ); + + // + // Remove Item From Temp Collection ... + ArrayRemove( + tmps, + idx, + 1 // + ); + } + + // + // Cleanup Collection if Max Items Reached ... + if (maxAllowed > 0) + { + // + CleanupArray( + source, + maxAllowed // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(tmps); +} + +/** + * Apply Sort on Specified Collection ... + * + * @param source: Collection Reference to Sort ... + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + * @param priceType: ENUM_X_PRICE, Price Selecting Method ... + * @param maxAllowed: int, Max Allowed Collection Size ... + */ +void SortBar( + XOHCL &source[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, + ENUM_X_PRICE priceType = X_PRICE_NONE, + int maxAllowed = 0 // +) +{ + // + int idx = -1; + bool has = false; + + // + // Validate ... + has = + IsXValid(sortBy) && + HasChild(source) && + HasDirection(sortDir); + if (!has) + { + return; + } + + // + // Copy source for Manipulating ... + XOHCL tmps[]; + Copy( + source, + tmps // + ); + + // + // Clean Source Collection for Adding Sorted Items ... + Clean(source); + + // + // Loop Through Temp Collection Has Child ... + while (HasChild(tmps)) + { + // + // Select Based on Sorting Parameter ... + idx = SelectBarForSorting( + tmps, + sortBy, + sortDir, + priceType // + ); + + // + // Validate Detected Index ... + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + // Add Detected Indexed Item to Source ... + AddRef( + tmps[idx], + source // + ); + + // + // Remove Item From Temp Collection ... + ArrayRemove( + tmps, + idx, + 1 // + ); + } + + // + // Cleanup Collection if Max Items Reached ... + if (maxAllowed > 0) + { + // + CleanupArray( + source, + maxAllowed // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(tmps); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Extraction | +//+------------------------------------------------------------------+ + +/** + * Extract Specific Types of Pivots From a Collection ... + * + * @param dest: reference Collection to Hold result ... + * @param source: Collection to Find Type Specific items ... + * @param _type: Specified item Type ... + * + * @return ( int ) + */ +int ExtractPivots( + XPivot &dest[], + XPivot &source[], + ENUM_X_PIVOT_TYPE _type // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + int count = ArraySize(source); + bool has = + IsXValid(_type) && + IsValidSize(count); + if (!has) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + // Check Type Passing ... + has = _type == source[i].type; + if (!has) + { + continue; + } + + // + AddIfNotExists( + source[i], + dest // + ); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract Same Time Pivots ... + * + * @param item: XPivot, reference to Specified Pivot for Detect Same Times ... + * @param dest: XPivot, collection reference to holds Same Times Pivots ... + * @param source: XPivot, collection reference to Provide Data Source ... + * + * @return ( int ) + */ +int ExtractSameTimePivots( + XPivot &item, + XPivot &dest[], + XPivot &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = HasChild(source) && + item.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = item.time == source[i].time; + if (has) + { + AddIfNotExists(source[i], dest); + } + } + + // + // Add item as a Child ... + AddIfNotExists(item, dest); + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract Pivots Data for Linear Regression Calculations ... + * + * @param xData: refrence Collection to Holds X-Axis Data ... + * @param yData: refrence Collection to Holds Y-Axis Data ... + * @param source: pivots Collection for Extraction ... + * + * @return ( int ) + */ +int ExtractPivotsData( + double &xData[], + double &yData[], + XPivot &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(xData); + SpecifiedClean(yData); + + // + // Validate ... + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + double iX = EMPTY_VALUE; + double iY = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + // Get Pivot Bar ... + has = source[i].GetBar(iBar); + if (!has) + { + continue; + } + + // + iX = iBar.Index(); + iY = source[i].value; + + // + Add( + iX, + xData // + ); + + // + Add( + iY, + yData // + ); + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + result = MathMin(ArraySize(xData), ArraySize(yData)); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Support and Resistance | +//+------------------------------------------------------------------+ +/** + * Extract Support Levels of Pivots Collection ... + * + * @param _minor: refrence to Holds Minor Level ... + * @param _major: refrence to Holds Major Level ... + * @param source: Collection of Pivots ... + * + * @return ( bool ) + */ +bool ExtractSupport( + double &_minor, + double &_major, + XPivot &source[] // +) +{ + // + bool result = false; + + // + // Prepare ... + _minor = EMPTY_VALUE; + _major = EMPTY_VALUE; + + // + // Validate ... + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + bool has = false; + double tmp = EMPTY_VALUE; + double iValue = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + // Check Type ... + has = source[i].IsVale(); + if (!has) + { + continue; + } + + // + // Reading Value ... + iValue = source[i].value; + + // + // Check Can Change Major ... + has = !NotEmpty(_major) || + _major > iValue; + if (has) + { + // + tmp = _major; + _major = iValue; + } + // + // Check Can Change Minor ... + else + { + // + // Change Minor ... + has = !NotEmpty(tmp) || + tmp > iValue; + if (has) + { + tmp = iValue; + } + } + } + + // + // Last Update of Minore Minor ... + has = NotEmpty(tmp); + if (has) + { + _minor = tmp; + } + + // + result = NotEmpty(_major) || + NotEmpty(_minor); + + // + return result; +} + +/** + * Extract Resistance Levels of Pivots Collection ... + * + * @param _minor: refrence to Holds Minor Level ... + * @param _major: refrence to Holds Major Level ... + * @param source: Collection of Pivots ... + * + * @return ( bool ) + */ +bool ExtractResistances( + double &_minor, + double &_major, + XPivot &source[] // +) +{ + // + bool result = false; + + // + // Prepare ... + _minor = EMPTY_VALUE; + _major = EMPTY_VALUE; + + // + // Validate ... + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + bool has = false; + double tmp = EMPTY_VALUE; + double iValue = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + // Check Type ... + has = source[i].IsPeak(); + if (!has) + { + continue; + } + + // + // Reading Value ... + iValue = source[i].value; + + // + // Check Can Change Major ... + has = !NotEmpty(_major) || + _major < iValue; + if (has) + { + // + tmp = _major; + _major = iValue; + } + // + // Check Can Change Minor ... + else + { + // + // Change Minor ... + has = !NotEmpty(tmp) || + tmp < iValue; + if (has) + { + tmp = iValue; + } + } + } + + // + // Last Update of Minore Minor ... + has = NotEmpty(tmp); + if (has) + { + _minor = tmp; + } + + // + result = NotEmpty(_major) || + NotEmpty(_minor); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Find Index | +//+------------------------------------------------------------------+ +/** + * Find Specified Item index in a Collection ... + * + * @param index: int, reference to Hold Index if Exists ... + * @param item: Specified item to Detect ... + * @param source: Collection to Search for item ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XBoxZone &item, + XBoxZone &source[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(source); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(source[i]); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Find Specified Item index in a Collection ... + * + * @param index: int, reference to Hold Index if Exists ... + * @param item: Specified item to Detect ... + * @param source: Collection to Search for item ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XPivot &item, + XPivot &source[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(source); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(source[i]); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Find Specified Item index in a Collection ... + * + * @param index: int, reference to Hold Index if Exists ... + * @param item: Specified item to Detect ... + * @param source: Collection to Search for item ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XDirectionShift &item, + XDirectionShift &source[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(source); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(source[i]); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Remove | +//+------------------------------------------------------------------+ +/** + * Remove Specified Item from a Collection ... + * + * @param item: Specified Item ... + * @param source: Specified Collection for Remove item from it ... + * + * @return ( bool ) + */ +bool Remove( + XPivot &item, + XPivot &source[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(source); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + source // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + source, + idx, + 1 // + ); + + // + return result; +} + +/** + * Remove Specified Item from a Collection ... + * + * @param item: Specified Item ... + * @param source: Specified Collection for Remove item from it ... + * + * @return ( bool ) + */ +bool Remove( + XBoxZone &item, + XBoxZone &source[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(source); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + source // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + source, + idx, + 1 // + ); + + // + return result; +} + +/** + * Remove Specified Item from a Collection ... + * + * @param item: Specified Item ... + * @param source: Specified Collection for Remove item from it ... + * + * @return ( bool ) + */ +bool Remove( + XDirectionShift &item, + XDirectionShift &source[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(source); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + source // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + source, + idx, + 1 // + ); + + // + return result; +} + +/** + * Remove Specified items from a Collection ... + * + * @param items: Specified Items to Remove ... + * @param sources: Sepcified Collection for Removing items from it ... + * + * @return ( int ) + */ +int Removes( + XBoxZone &items[], + XBoxZone &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int idx = -1; + has = false; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Detect Item Index in Collection ... + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + // Remove Detected Index from Collection ... + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + // + // Count Removed Items ... + result++; + } + } + } + + // + return result; +} + +/** + * Remove Specified items from a Collection ... + * + * @param items: Specified Items to Remove ... + * @param sources: Sepcified Collection for Removing items from it ... + * + * @return ( int ) + */ +int Removes( + XPivot &items[], + XPivot &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int idx = -1; + has = false; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Detect Item Index in Collection ... + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + // Remove Detected Index from Collection ... + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + // + // Count Removed Items ... + result++; + } + } + } + + // + return result; +} + +/** + * Remove Specified items from a Collection ... + * + * @param items: Specified Items to Remove ... + * @param sources: Sepcified Collection for Removing items from it ... + * + * @return ( int ) + */ +int Removes( + XDirectionShift &items[], + XDirectionShift &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int idx = -1; + has = false; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Detect Item Index in Collection ... + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + // Remove Detected Index from Collection ... + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + // + // Count Removed Items ... + result++; + } + } + } + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Add If Not Exists | +//+------------------------------------------------------------------+ +/** + * Add Specified Item to Specified Collection, if not Exists ... + * + * @param item: Item to Add ... + * @param sources: Collection to Add item ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XBoxZone &item, + XBoxZone &sources[], + int maxAllowed = 0 // +) +{ + // + 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 // + ); + + // + // Handle Cleanup Collection + // if Max Reached ... + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +/** + * Add Specified Item to Specified Collection, if not Exists ... + * + * @param item: Item to Add ... + * @param sources: Collection to Add item ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XPivot &item, + XPivot &sources[], + int maxAllowed = 0 // +) +{ + // + 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 // + ); + + // + // Handle Cleanup Collection + // if Max Reached ... + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +/** + * Add Specified Item to Specified Collection, if not Exists ... + * + * @param item: Item to Add ... + * @param sources: Collection to Add item ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XDirectionShift &item, + XDirectionShift &sources[], + int maxAllowed = 0 // +) +{ + // + 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 // + ); + + // + // Handle Cleanup Collection + // if Max Reached ... + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +template +int FillNotExists( + T &dest[], + T &source[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int maxAllowed = 0 // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + maxAllowed = NormalizeInt(maxAllowed, 0); + + // + // Validate ... + bool has = HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = + source[i].IsValid() && + (!HasDirection(forDir) || forDir == source[i].dir); + if (!has) + { + continue; + } + + // + has = AddIfNotExists(source[i], dest); + if (has) + { + result++; + } + } + + // + // Handle Cleanup Collection + // if Max Reached ... + if (maxAllowed > 0) + { + // + CleanupArray( + dest, + maxAllowed // + ); + } + + // + return result; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Extract | +//+------------------------------------------------------------------+ + +/** + * Extract Specified Directional Items ... + * + * @param dest: reference collection to holds extracted items ... + * @param source: reference collection to provides data source ... + * @param forDir: Specified which direction to Extract items ... + * + * @return ( int ) + */ +template +int ExtractByDirection( + T &dest[], + T &source[], + ENUM_X_DIRECTION forDir // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = HasChild(source) && + HasDirection(forDir); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = source[i].dir == forDir; + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} +//+------------------------------------------------------------------+ + +// +// +// + +//+------------------------------------------------------------------+ +//| Other Extensions | +//+------------------------------------------------------------------+ + +/** + * 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 // + ); + } + } + + // +} + +void UpdateToTime( + XBoxZone &zones[], + datetime toTime = NULL // +) +{ + // + // Normalize ... + toTime = NormalizeTime(toTime); + + // + // Validate ... + bool has = HasChild(zones); + if (!has) + { + return; + } + + // + int count = ArraySize(zones); + for (int i = 0; i < count; i++) + { + zones[i].to = toTime; + } +} + +/** + * Remove Breaked Zones from a Collection ... + * + * @param source: XBoxZone, reference to Specified Collection ... + * + * @return ( int ) + */ +int RemoveBreakedZones( + XBoxZone &source[], + bool forceBreak = false // +) +{ + // + int result = 0; + + // + // Validate ... + bool has = HasChild(source); + if (!has) + { + return result; + } + + // + XBoxZone iZone; + XBoxZone tmps[]; + Copy( + source, + tmps // + ); + XClean(source); + XOHCL tmpBars[]; + int breakerBars = 0; + while (HasChild(tmps)) + { + // + iZone.Clean(); + iZone = tmps[0]; + ArrayRemove(tmps, 0, 1); + has = IsXValid(iZone.breakAt); + if (has) + { + continue; + } + + // + if (forceBreak) + { + // + breakerBars = GetBreakerBars(iZone, tmpBars); + has = IsValidSize(breakerBars); + } + if (has) + { + continue; + } + + // + AddIfNotExists( + iZone, + source // + ); + } + + // + result = ArraySize(source); + + // + return result; +} + +/** + * Remove Filled Zones ... + * + * @param source: XBoxZone, collection reference to Provide Data Source ... + * @param zoneRangeFilledFactor: double, Filling Factor ... + * + * @return ( int ) + */ +int RemoveFilledZones( + XBoxZone &source[], + double zoneRangeFilledFactor = 0.8 // +) +{ + // + int result = 0; + + // + // Validate ... + bool has = HasChild(source); + if (!has) + { + return result; + } + + // + XBoxZone iTMP; + XBoxZone tmp[]; + Copy(source, tmp); + XClean(source); + while (HasChild(tmp)) + { + // + iTMP.Clean(); + iTMP = tmp[0]; + ArrayRemove(tmp, 0, 1); + + // + has = IsFilled(iTMP, zoneRangeFilledFactor); + if (!has) + { + AddIfNotExists(iTMP, source); + } + } + + // + result = ArraySize(source); + + // + return result; +} + +// #region Zone Converters ... +/** + * Converts a Bar to Pivot ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param pivot: XPivot, reference to holds result ... + * @param forDir: ENUM_X_DIRECTION, specified Pivot Direction ... + * @param prefix: string, Specified Pivot Prefix (used for Object Type) ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... + * + * @return ( bool ) + */ +bool ToPivot( + XOHCL &bar, + XPivot &pivot, + ENUM_X_DIRECTION forDir, + string prefix = NULL, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW // +) +{ + // + bool result = false; + + // + // Prepare ... + pivot.Clean(); + + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir) && + IsXValid(peakPriceType) && + IsXValid(valePriceType); + if (!result) + { + return result; + } + + // + // Check Direction ... + bool isBullish = IsSpecifiedBullish(forDir); + + // + // Prepare Value of Pivot ... + double iValue = + isBullish + ? bar.GetPrice(valePriceType) + : bar.GetPrice(peakPriceType); + + // + // Prepare Pivot Type ... + ENUM_X_PIVOT_TYPE iType = + isBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_PEAK; + + // + // Initialize Pivot ... + result = pivot.Init( + iValue, + bar.time, + bar.symbol, + forDir, + bar.period, + iType // + ); + if (result) + { + // + // Set Prefix if Pivot initialized successfully ... + pivot.prefix = prefix; + } + + // + // Validate ... + result = pivot.IsValid(); + if (!result) + { + pivot.Clean(); + } + + // + return result; +} + +/** + * Converts a Bar to Pattern Pivot ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param pivot: XPivot, reference to holds result ... + * @param patternDir: ENUM_X_DIRECTION, specified Pivot Direction ... + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern Type ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... + * + * @return ( bool ) + */ +bool ToPivot( + XOHCL &bar, + XPivot &pivot, + ENUM_X_DIRECTION patternDir, + ENUM_X_BAR_PATTERN pattern, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW // +) +{ + // + bool result = false; + + // + // Prepare ... + pivot.Clean(); + + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = bar.IsValid() && + IsXValid(pattern) && + IsXValid(peakPriceType) && + IsXValid(valePriceType) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + datetime iTime = bar.time; + string iSymbol = bar.symbol; + string iPrefix = ToXString(pattern); + ENUM_TIMEFRAMES iPeriod = bar.period; + double iValue = IsXBullish(patternDir) + ? bar.GetPrice(X_PRICE_LOW) + : IsXBearish(patternDir) + ? bar.GetPrice(X_PRICE_HIGH) + : EMPTY_VALUE; + ENUM_X_PIVOT_TYPE iType = IsXBullish(patternDir) + ? X_PIVOT_TYPE_VALE + : IsXBearish(patternDir) + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + + // + result = pivot.Init( + iValue, + iTime, + iSymbol, + patternDir, + iPeriod, + iType // + ); + if (result) + { + pivot.prefix = iPrefix; + } + + // + // Cleanup Resources ... + if (!result) + { + pivot.Clean(); + } + + // + return result; +} + +/** + * Converts POI Bar to Box ... + * + * @param bar: XOHCL, reference to Specified Pattern ... + * @param box: XBoxZone, reference to holds result ... + * @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * @param prefix: string, Specified Pattern Type ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... + * @param setFromByBreakerBar: bool, Set Box From Time to Breaker Bar ... + * + * @return ( bool ) + */ +bool ToBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION forDir, + string prefix = NULL, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW, + bool setFromByBreakerBar = false // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir) && + IsXValid(peakPriceType) && + IsXValid(valePriceType); + if (!result) + { + return result; + } + + // + // Check if is Valid Pattern ... + ENUM_X_BAR_PATTERN iPattern = ToBarPattern(prefix); + result = IsXValid(iPattern); + if (result) + { + // + // Conver to Box as Pattern ... + result = ToBox( + bar, + box, + forDir, + iPattern, + peakPriceType, + valePriceType, + setFromByBreakerBar // + ); + } + // + // There is not any Valid Pattern Provided ... + else + { + // + bool isBullish = IsXBullish(forDir); + double peakPrice = bar.GetPrice(peakPriceType); + double valePrice = bar.GetPrice(valePriceType); + + // + string iType = prefix; + datetime iAt = bar.time; + datetime iTo = bar.time; + double iUpper = peakPrice; + double iLower = valePrice; + string iSymbol = bar.symbol; + datetime iFrom = bar.BeforeOn(); + ENUM_TIMEFRAMES iPeriod = bar.period; + + // + // Assign Values to Box ... + box.at = iAt; + box.to = iTo; + box.from = iFrom; + box.type = iType; + box.dir = forDir; + box.upper = iUpper; + box.lower = iLower; + box.symbol = iSymbol; + box.period = iPeriod; + } + + // + // Validate result ... + result = box.IsValid(); + if (!result) + { + // + box.Clean(); + return result; + } + + // + return result; +} + +/** + * Converts Pattern Bar to Box ... + * + * @param bar: XOHCL, reference to Specified Pattern ... + * @param box: XBoxZone, reference to holds result ... + * @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * @param prefix: string, Specified Pattern Type ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... + * @param setFromByBreakerBar: bool, Set Box From Time to Breaker Bar ... + * + * @return ( bool ) + */ +bool ToBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION patternDir, + ENUM_X_BAR_PATTERN pattern, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW, + bool setFromByBreakerBar = false // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = bar.IsValid() && + IsXValid(pattern) && + IsXValid(peakPriceType) && + IsXValid(valePriceType) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + // Define Requirements ... + XOHCL tmpBar; + XBoxZone tmpBox; + bool has = false; + datetime iAt = bar.time; + datetime iTo = bar.time; + double iUpper = EMPTY_VALUE; + double iLower = EMPTY_VALUE; + string iSymbol = bar.symbol; + datetime iFrom = bar.BeforeOn(); + string iType = ToXString(pattern); + ENUM_TIMEFRAMES iPeriod = bar.period; + + // + bool isBullish = IsXBullish(patternDir); + double peakPrice = bar.GetPrice(peakPriceType); + double valePrice = bar.GetPrice(valePriceType); + + // + // Calculate Requirements Based on Pattern Type and Direction ... + switch (pattern) + { + // + case X_BAR_PATTERN_HIGH: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + has = GetBreakerBar( + bar, + tmpBar, + peakPriceType, + peakPriceType, + X_DIRECTION_BULLISH // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = peakPrice; + iLower = bar.GetUp(); + } + break; + + // + case X_BAR_PATTERN_LOW: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + has = GetBreakerBar( + bar, + tmpBar, + valePriceType, + valePriceType, + X_DIRECTION_BEARISH // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = bar.GetDown(); + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_MOMENTUM: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = peakPrice; + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_ENGULFED: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = peakPrice; + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_TRUE_GAPED: { + // + tmpBar.Clean(); + has = bar.GetPreviousBar(tmpBar); + if (has) + { + // + iFrom = tmpBar.time; + + // + iUpper = + isBullish + ? valePrice + : tmpBar.GetPrice(valePriceType); + iLower = + isBullish + ? tmpBar.GetPrice(peakPriceType) + : peakPrice; + } + } + break; + + // + case X_BAR_PATTERN_PINNED: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = + isBullish + ? bar.GetDown() + : peakPrice; + iLower = + isBullish + ? valePrice + : bar.GetUp(); + } + break; + + // + case X_BAR_PATTERN_STAR: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + // + if (setFromByBreakerBar) + { + iFrom = tmpBar.time; + } + + // + int idx = -1; + int mLength = tmpBar.Index() - bar.Index(); + iLower = bar.FindLowest(idx, mLength, valePriceType); + iUpper = bar.FindHighest(idx, mLength, peakPriceType); + } + } + break; + + // + case X_BAR_PATTERN_PIERCING: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = peakPrice; + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_RISING: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = peakPrice; + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_FLAG: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + int idx = -1; + int mLength = 3; + iUpper = bar.FindHighest(idx, mLength, peakPriceType); + iLower = bar.FindLowest(idx, mLength, valePriceType); + } + break; + + // + case X_BAR_PATTERN_SIGNALKEY: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + has = bar.GetPreviousBar(tmpBar); + if (has) + { + // + iUpper = MathMax(peakPrice, tmpBar.GetPrice(peakPriceType)); + iLower = MathMin(valePrice, tmpBar.GetPrice(valePriceType)); + } + } + break; + + // + case X_BAR_PATTERN_OB: { + // + tmpBox.Clean(); + has = ToOBBox( + bar, + tmpBox, + patternDir // + ); + if (has) + { + // + iFrom = tmpBox.from; + iUpper = tmpBox.upper; + iLower = tmpBox.lower; + } + } + break; + + // + case X_BAR_PATTERN_FVG: { + // + tmpBox.Clean(); + has = ToFVGBox( + bar, + tmpBox, + patternDir // + ); + if (has) + { + // + iFrom = tmpBox.from; + iUpper = tmpBox.upper; + iLower = tmpBox.lower; + } + } + break; + + // + case X_BAR_PATTERN_SUPPORT: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_RESISTANCE: { + // + if (setFromByBreakerBar) + { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + } + + // + // Assign Values to Box ... + box.at = iAt; + box.to = iTo; + box.from = iFrom; + box.type = iType; + box.upper = iUpper; + box.lower = iLower; + box.symbol = iSymbol; + box.period = iPeriod; + box.dir = patternDir; + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + box.Clean(); + } + tmpBar.Clean(); + tmpBox.Clean(); + + // + return result; +} + +/** + * Converts Order Flow to Zone ... + * + * @param zone: XBoxZone, reference to holds result ... + * @param orderFlow: XBoxZone, collection reference to provides order flow ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &zone, + XBoxZone &orderFlow[] // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Validate ... + result = HasChild(orderFlow); + if (!result) + { + return result; + } + + // + zone = orderFlow[0]; + int idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + zone.upper = orderFlow[idx].upper; + } + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + zone.lower = orderFlow[idx].lower; + } + + // + zone.type = "XOrderFlowP"; + + // + result = zone.IsValid(); + + // + return result; +} + +/** + * Converts a Bar to OB Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( bool ) + */ +bool ToOBBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!HasDirection(forDir)) + { + forDir = bar.GetDirection(); + } + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir) && + bar.GetDirection() == forDir; + if (!result) + { + return result; + } + + // + // Detect OB Start Bar ... + XOHCL obStartBar; + result = GetDirectionalBar( + bar, + obStartBar, + Opposit(forDir) // + ); + if (!result) + { + // + obStartBar.Clean(); + return result; + } + + // + box.dir = forDir; + box.to = bar.time; + box.at = bar.time; + box.symbol = bar.symbol; + box.period = bar.period; + box.from = obStartBar.time; + box.type = ToXString(X_BAR_PATTERN_OB); + box.lower = MathMin(obStartBar.low, bar.low); + box.upper = MathMax(obStartBar.high, bar.high); + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + box.Clean(); + } + obStartBar.Clean(); + + // + return result; +} + +/** + * Converts a Bar to FVG Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( bool ) + */ +bool ToFVGBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!HasDirection(forDir)) + { + forDir = bar.GetDirection(); + } + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir) && + bar.GetDirection() == forDir; + if (!result) + { + return result; + } + + // + // Detect FVG Start Bar ... + XOHCL fvgStartBar; + result = bar.BarAt( + bar.Index() + 2, + fvgStartBar); + if (!result) + { + // + fvgStartBar.Clean(); + return result; + } + + // + bool isBullish = IsXBullish(forDir); + + // + box.dir = forDir; + box.to = bar.time; + box.at = bar.time; + box.upper = + isBullish + ? bar.low + : bar.high; + box.symbol = bar.symbol; + box.period = bar.period; + box.lower = + isBullish + ? fvgStartBar.high + : fvgStartBar.low; + box.from = fvgStartBar.time; + box.type = ToXString(X_BAR_PATTERN_FVG); + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + box.Clean(); + } + fvgStartBar.Clean(); + + // + return result; +} + +/** + * 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, + int validationLength = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + toTime = NormalizeTime(toTime); + validationLength = NormalizeInt(validationLength, 0); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL breaker; + result = GetBreakerBar( + bar, + breaker, + X_PRICE_LOW, + X_PRICE_DOWN, + X_DIRECTION_BEARISH, + 500 // + ); + if (!result) + { + breaker.Clean(); + } + + // + box.to = toTime; + box.at = bar.time; + box.from = + breaker.IsValid() + ? breaker.time + : validationLength <= 0 + ? bar.time + : GetBarTime( + bar.symbol, + bar.period, + bar.Index() + validationLength // + ); + box.lower = bar.low; + box.symbol = bar.symbol; + box.period = bar.period; + box.upper = bar.GetDown(); + box.dir = X_DIRECTION_BULLISH; + box.type = ToXString(X_BAR_PATTERN_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, + int validationLength = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + toTime = NormalizeTime(toTime); + validationLength = NormalizeInt(validationLength, 0); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL breaker; + result = GetBreakerBar( + bar, + breaker, + X_PRICE_HIGH, + X_PRICE_UP, + X_DIRECTION_BULLISH, + 500 // + ); + if (!result) + { + breaker.Clean(); + } + + // + box.to = toTime; + box.at = bar.time; + box.from = + breaker.IsValid() + ? breaker.time + : validationLength <= 0 + ? bar.time + : GetBarTime( + bar.symbol, + bar.period, + bar.Index() + validationLength // + ); + box.upper = bar.high; + box.symbol = bar.symbol; + box.period = bar.period; + box.lower = bar.GetUp(); + box.dir = X_DIRECTION_BEARISH; + box.type = ToXString(X_BAR_PATTERN_RESISTANCE); + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; +} +// #endregion + +// #region Zone Checkers ... +/** + * Check a Zone is Filled or Not ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param zoneRangeFilledFactor: double, Filling Factor ... + * + * @return ( bool ) + */ +bool IsFilled( + XBoxZone &zone, + double zoneRangeFilledFactor = 0.8 // +) +{ + // + bool result = false; + + // + // Validate ... + result = zone.IsValid() && + zoneRangeFilledFactor > 0 && + zoneRangeFilledFactor < 1; + if (!result) + { + // + result = true; + return result; + } + + // + XOHCL iBar; + int toIDX = zone.ToIndex(); + int fromIDX = zone.FromIndex(); + double zoneRangeFactor = zone.GetRange() / 100; + double useValue = zone.lower + (zoneRangeFactor * zoneRangeFilledFactor); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + result = iBar.Init(zone.symbol, zone.period, i); + result = + result && + (zone.IsBullish() + ? iBar.GetPrice(X_PRICE_LOW) <= useValue + : iBar.GetPrice(X_PRICE_HIGH) >= useValue); + if (result) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Specified Zone is Breaked by Specified Bar or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * @param forceBarEdge: bool, flag to Check Breaktion by high ot low ... + * + * @return ( bool ) + */ +bool IsBreaked( + XOHCL &bar, + XBoxZone &zone, + bool forceBarEdge = false // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Check Break ... + result = + zone.IsBullish() + ? bar.close < zone.lower + : bar.close > zone.upper; + + // + // Apply Force Bar Edge ... + if (forceBarEdge) + { + // + result = + result && + zone.IsBullish() + ? bar.low > zone.upper + : bar.high < zone.lower; + } + + // + return result; +} + +/** + * Check Specified Zone is Tested by Specified Bar or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ +bool IsTested( + XOHCL &bar, + XBoxZone &zone // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Check Test ... + result = + zone.IsBullish() + ? bar.low < zone.upper && bar.low > zone.lower + : bar.high > zone.lower && + bar.high < zone.upper; + + // + return result; +} + +/** + * Check Specified Zone is Rejected by Specified Bar or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ +bool IsRejected( + XOHCL &bar, + XBoxZone &zone // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Check Test ... + result = + IsTested(bar, zone) && + (zone.IsBullish() + ? bar.GetDown() >= zone.upper + : bar.GetUp() <= zone.lower); + + // + return result; +} + +/** + * Check Specified Bar is Inside Specified Zone or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ +bool IsInside( + XOHCL &bar, + XBoxZone &zone // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Check Inside ... + result = + zone.IsBullish() + ? bar.low < zone.upper && + bar.low > zone.lower + : bar.high > zone.lower && + bar.high < zone.upper; + + // + return result; +} + +/** + * Check Specified Bar is Acted On Specified Zone or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ +bool IsActed( + XOHCL &bar, + XBoxZone &zone // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Get Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Previous Bar must one of Following States: + // - Tested; + // - Inside; + // - Breaked; + bool isTested = IsTested(pBar, zone); + bool isInside = IsInside(pBar, zone); + bool isBreaked = IsBreaked(pBar, zone); + result = isTested || + isInside || + isBreaked; + if (!result) + { + return result; + } + + // + // Current Bar Must Close Over / Under Zone ... + result = + zone.IsBullish() + ? bar.close > zone.upper + : zone.IsBearish() + ? bar.close < zone.lower + : false; + + // + // Cleanup Resources ... + pBar.Clean(); + + // + return result; +} + +/** + * Check Specified Zone is Breaked or not ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param priceType: ENUM_X_PRICE, Specified Price Type for Zone Break Detection ... + * + * @return ( bool ) + */ +bool IsBreaked( + XBoxZone &zone, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // +) +{ + // + bool result = false; + + // + // Validate ... + result = zone.IsValid() && + IsXValid(priceType); + if (!result) + { + // + result = true; + return result; + } + + // + XOHCL iBar; + double iPrice; + bool isBullish; + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + result = iBar.Init(zone.symbol, zone.period, i); + if (!result) + { + // + result = true; + break; + } + + // + isBullish = zone.IsBullish(); + iPrice = iBar.GetPrice(priceType); + result = isBullish + ? iPrice < zone.lower + : iPrice > zone.upper; + if (result) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar is Acted On Specified Zone or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * @param validationLength: Specified Length for Breaks ... + * + * @return ( bool ) + */ +bool IsValidBreaked( + XOHCL &bar, + XBoxZone &zone, + int validationLength = 3 // +) +{ + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + int count = 0; + int start = bar.Index(); + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + result = bar.BarAt(i, iBar); + if (!result) + { + break; + } + + // + result = IsBreaked(iBar, zone); + if (result) + { + count++; + } + } + + // + result = IsValidSize(count) && + count >= validationLength; + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar is Fake Breaked Specified Zone or not ... + * + * @param bar: Specified Bar ... + * @param zone: Specified Zone ... + * @param validationLength: Specified Length for Breaks ... + * + * @return ( bool ) + */ +bool IsFakeBreaked( + XOHCL &bar, + XBoxZone &zone, + int validationLength = 3 // +) +{ + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Check Bar Must Acting Zone ... + result = zone.IsBullish() + ? bar.close > zone.upper + : zone.IsBearish() + ? bar.close < zone.lower + : false; + if (!result) + { + return result; + } + + // + // Detect Breaker Bars ... + XOHCL breakerBars[]; + int breakerBarsCount = GetBreakerBars( + zone, + breakerBars // + ); + result = IsValidSize(breakerBarsCount); + if (!result) + { + // + XClean(breakerBars); + return result; + } + + // + // Get Youngest Breaker Bars ... + int idx = GetYoungest(breakerBars); + result = IsValidIndex(idx); + if (!result) + { + // + XClean(breakerBars); + return result; + } + + // + result = breakerBars[idx].Index() - bar.Index() <= validationLength; + + // + // Cleanup Resources ... + XClean(breakerBars); + + // + return result; +} + +/** + * Check Specified ZOne is Affected by Specified Bar or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zone: XBoxZone, reference to Specified Zone ... + * + * @return ( bool ) + */ +bool IsZoneAffected( + XOHCL &bar, + XBoxZone &zone // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isActed = IsActed(bar, zone); + bool isTested = IsTested(bar, zone); + bool isFakeBreaked = IsFakeBreaked(bar, zone); + + // + result = isActed || + isTested || + isFakeBreaked; + + // + return result; +} +// #endregion + +// #region Zones Hasers ... +/** + * Check a Bar is Inside a Zone or not ... + * + * @param index: int, reference to holds detected index ... + * @param bar: reference to Specified Bar ... + * @param source: reference collection to provide source ... + * + * @return ( bool ) + */ +bool HasInside( + int &index, + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + XBoxZone selected[]; + int count = ExtractInsides(bar, selected, source); + bool result = IsValidSize(count); + if (result) + { + // + index = GetYoungest(selected); + if (IsValidIndex(index)) + { + result = FindIndex(index, selected[index], source); + } + } + + // + XClean(selected); + + // + return result; +} + +/** + * Check a Bar is Reject a Zone or not ... + * + * @param index: int, reference to holds detected index ... + * @param bar: reference to Specified Bar ... + * @param source: reference collection to provide source ... + * + * @return ( bool ) + */ +bool HasRejected( + int &index, + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + XBoxZone selected[]; + int count = ExtractRejecteds(bar, selected, source); + bool result = IsValidSize(count); + if (result) + { + // + index = GetYoungest(selected); + if (IsValidIndex(index)) + { + result = FindIndex(index, selected[index], source); + } + } + + // + XClean(selected); + + // + return result; +} + +/** + * Check a Bar is Break a Zone or not ... + * + * @param index: int, reference to holds detected index ... + * @param bar: reference to Specified Bar ... + * @param source: reference collection to provide source ... + * + * @return ( bool ) + */ +bool HasBreaked( + int &index, + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + XBoxZone selected[]; + int count = ExtractBreakeds(bar, selected, source); + bool result = IsValidSize(count); + if (result) + { + // + index = GetYoungest(selected); + if (IsValidIndex(index)) + { + result = FindIndex(index, selected[index], source); + } + } + + // + XClean(selected); + + // + return result; +} + +/** + * Check a Bar is Act a Zone or not ... + * + * @param index: int, reference to holds detected index ... + * @param bar: reference to Specified Bar ... + * @param source: reference collection to provide source ... + * + * @return ( bool ) + */ +bool HasActed( + int &index, + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + XBoxZone selected[]; + int count = ExtractActeds(bar, selected, source); + bool result = IsValidSize(count); + if (result) + { + // + index = GetYoungest(selected); + if (IsValidIndex(index)) + { + result = FindIndex(index, selected[index], source); + } + } + + // + XClean(selected); + + // + return result; +} +// #endregion + +// #region Zone Extractors ... +/** + * Extract Affected Zones for Specified Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param source: XBoxZone, reference collection to Provide Data Source ... + * @param dest: XBoxZone, reference collection to holds result ... + * @param forDir: ENUM_X_DIRECTION, Specified Zones Direction to Lookup ... + * + * @return ( int ) + */ +int ExtractAffectedZones( + XOHCL &bar, + XBoxZone &source[], + XBoxZone &dest[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(source); + if (!has) + { + return result; + } + + // + bool isActed; + bool isTested; + bool isInside; + bool isFakeBreaked; + for (int i = 0; i < ArraySize(source); i++) + { + // + // Validate Direction ... + has = + !HasDirection(forDir) || + forDir == source[i].dir; + if (!has) + { + continue; + } + + // + // Check Affected ... + isActed = IsActed(bar, source[i]); + isTested = IsTested(bar, source[i]); + isInside = IsInside(bar, source[i]); + isFakeBreaked = IsFakeBreaked(bar, source[i]); + + // + has = + isActed || + isTested || + isInside || + isFakeBreaked; + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all Items which Specified Bar is inside them ... + * + * @param bar: reference to Specified Bar ... + * @param dest: reference to result ... + * @param source: reference collection to provide source ... + * + * @return ( int ) + */ +int ExtractInsides( + XOHCL &bar, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = IsInside( + bar, + source[i] // + ); + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all Items which Specified Bar is Acted them ... + * + * @param bar: reference to Specified Bar ... + * @param dest: reference to result ... + * @param source: reference collection to provide source ... + * + * @return ( int ) + */ +int ExtractActeds( + XOHCL &bar, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = IsActed( + bar, + source[i] // + ); + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all Items which Specified Bar is Breaked them ... + * + * @param bar: reference to Specified Bar ... + * @param dest: reference to result ... + * @param source: reference collection to provide source ... + * + * @return ( int ) + */ +int ExtractBreakeds( + XOHCL &bar, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = IsBreaked( + bar, + source[i] // + ); + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract all Items which Specified Bar is Rejected them ... + * + * @param bar: reference to Specified Bar ... + * @param dest: reference to result ... + * @param source: reference collection to provide source ... + * + * @return ( int ) + */ +int ExtractRejecteds( + XOHCL &bar, + XBoxZone &dest[], + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = IsRejected( + bar, + source[i] // + ); + if (has) + { + // + AddIfNotExists( + source[i], + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Collect all Bars which Breakes Specified Zone ... + * + * @param zone: reference to Specified Zone ... + * @param dest: reference Collection to hold result ... + * + * @return ( int ) + */ +int GetBreakerBars( + XBoxZone &zone, + XOHCL &dest[] // +) +{ + // + int result = 0; + + // + // Validate ... + bool has = zone.IsValid(); + if (!has) + { + return result; + } + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Do Action ... + XOHCL iBar; + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i < end; i++) + { + // + // Initialize indexed Bar ... + has = iBar.Init( + zone.symbol, + zone.period, + i // + ); + if (!has) + { + continue; + } + + // + has = IsBreaked( + iBar, + zone, + false // Breakes by Close ... + ); + if (has) + { + // + AddIfNotExists( + iBar, + dest // + ); + } + + // + iBar.Clean(); + } + + // + result = ArraySize(dest); + + // + iBar.Clean(); + + // + return result; +} + +/** + * Collect all Bars which Inside Specified Zone ... + * + * @param zone: reference to Specified Zone ... + * @param dest: reference Collection to hold result ... + * + * @return ( int ) + */ +int GetInsideBars( + XBoxZone &zone, + XOHCL &dest[] // +) +{ + // + int result = 0; + + // + // Validate ... + bool has = zone.IsValid(); + if (!has) + { + return result; + } + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Do Action ... + XOHCL iBar; + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i < end; i++) + { + // + // Initialize indexed Bar ... + has = iBar.Init( + zone.symbol, + zone.period, + i // + ); + if (!has) + { + continue; + } + + // + has = IsInside( + iBar, + zone // + ); + if (has) + { + // + AddIfNotExists( + iBar, + dest // + ); + } + + // + iBar.Clean(); + } + + // + result = ArraySize(dest); + + // + iBar.Clean(); + + // + return result; +} + +/** + * Collect all Bars which Tested Specified Zone ... + * + * @param zone: reference to Specified Zone ... + * @param dest: reference Collection to hold result ... + * + * @return ( int ) + */ +int GetTesterBars( + XBoxZone &zone, + XOHCL &dest[] // +) +{ + // + int result = 0; + + // + // Validate ... + bool has = zone.IsValid(); + if (!has) + { + return result; + } + + // + // Prepare ... + SpecifiedClean(dest); + + // + // Do Action ... + XOHCL iBar; + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i < end; i++) + { + // + // Initialize indexed Bar ... + has = iBar.Init( + zone.symbol, + zone.period, + i // + ); + if (!has) + { + continue; + } + + // + has = IsTested( + iBar, + zone // + ); + if (has) + { + // + AddIfNotExists( + iBar, + dest // + ); + } + + // + iBar.Clean(); + } + + // + result = ArraySize(dest); + + // + iBar.Clean(); + + // + return result; +} + +/** + * Validate Zones Range ... + * + * @param source: XBoxZone, collection reference to Validate ... + * @param minAllowedRange: double, min allowed range to Validate ... + * + * @return ( int ) + */ +int ValidateZonesRange( + XBoxZone &source[], + double minAllowedRange // +) +{ + // + int result = 0; + + // + // Validate ... + bool has = HasChild(source) && + minAllowedRange > 0; + if (!has) + { + return result; + } + + // + XBoxZone iTMP; + XBoxZone tmps[]; + Copy(source, tmps); + XClean(source); + while (HasChild(tmps)) + { + // + iTMP.Clean(); + iTMP = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + // Check Range Validation ... + has = iTMP.GetRange() > minAllowedRange; + if (has) + { + AddIfNotExists(iTMP, source); + } + } + + // + result = ArraySize(source); + + // + // Cleanup ... + XClean(tmps); + iTMP.Clean(); + + // + return result; +} + +/** + * Remove Breaked Zones ... + * + * @param source: XBoxZone, collection reference to Remove Breaked Zones ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Break Detection ... + * + * @return ( int ) + */ +int RemoveBreakedZones( + XBoxZone &source[], + ENUM_X_PRICE priceType = X_PRICE_CLOSE // +) +{ + // + int result = 0; + + // + // Validate ... + if (!HasChild(source) || !IsXValid(priceType)) + { + return result; + } + + // + XBoxZone tmp[]; + Copy(source, tmp); + XClean(source); + XBoxZone iTMP; + bool isBreaked = false; + while (HasChild(tmp)) + { + // + iTMP.Clean(); + iTMP = tmp[0]; + ArrayRemove(tmp, 0, 1); + + // + isBreaked = IsBreaked(iTMP, priceType); + if (!isBreaked) + { + // + AddIfNotExists(iTMP, source); + } + } + + // + result = ArraySize(source); + + // + // Cleanup ... + XClean(tmp); + iTMP.Clean(); + + // + return result; +} +// #endregion +//+------------------------------------------------------------------+ + +// \ No newline at end of file diff --git a/BKPS/14041018/Libraries/x-saherelm.x-poi.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-poi.lib.mq5 new file mode 100644 index 0000000..155aa67 --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.x-poi.lib.mq5 @@ -0,0 +1,2207 @@ +/////////////////////////////////////////////////////// +// +// 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 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.common.lib.mq5" +#include + +// +// Definitions ... + +/** + * All Available Market Patterns ... + **/ +enum ENUM_X_BAR_PATTERN +{ + X_BAR_PATTERN_NONE = 0, + X_BAR_PATTERN_HIGH = 1, + X_BAR_PATTERN_LOW = 2, + X_BAR_PATTERN_MOMENTUM = 3, + X_BAR_PATTERN_ENGULFED = 4, + X_BAR_PATTERN_TRUE_GAPED = 5, + X_BAR_PATTERN_PINNED = 6, + X_BAR_PATTERN_STAR = 7, + X_BAR_PATTERN_PIERCING = 8, + X_BAR_PATTERN_RISING = 9, + X_BAR_PATTERN_FLAG = 10, + X_BAR_PATTERN_SIGNALKEY = 11, + X_BAR_PATTERN_OB = 12, + X_BAR_PATTERN_FVG = 13, + X_BAR_PATTERN_SUPPORT = 14, + X_BAR_PATTERN_RESISTANCE = 15, + X_BAR_PATTERN_PULLBACK = 16, + X_BAR_PATTERN_CONSOLIDATION = 17, + X_BAR_PATTERN_LEG = 18, +}; + +/** + * Validate an ENUM member ... + * + * @param value: ENUM_X_BAR_PATTERN ... + * + * @return ( bool ) + */ +bool IsXValid(ENUM_X_BAR_PATTERN value) +{ + return value != X_BAR_PATTERN_NONE; +} + +/** + * Converts a Pattern ENUM to String Representation ... + * + * @param value: ENUM_X_BAR_PATTERN, member ... + * + * @return ( string ) + */ +string ToXString(ENUM_X_BAR_PATTERN value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_BAR_PATTERN_NONE: + result = "X_NONE"; + break; + + // + case X_BAR_PATTERN_HIGH: + result = "XHIGHP"; + break; + + // + case X_BAR_PATTERN_LOW: + result = "XLOWP"; + break; + + // + case X_BAR_PATTERN_MOMENTUM: + result = "XMOMENTUMP"; + break; + + // + case X_BAR_PATTERN_ENGULFED: + result = "XENGULFEDP"; + break; + + // + case X_BAR_PATTERN_TRUE_GAPED: + result = "XGAPEDP"; + break; + + // + case X_BAR_PATTERN_PINNED: + result = "XPINNEDP"; + break; + + // + case X_BAR_PATTERN_STAR: + result = "XSTARP"; + break; + + // + case X_BAR_PATTERN_PIERCING: + result = "XPIERCINGP"; + break; + + // + case X_BAR_PATTERN_RISING: + result = "XRISINGP"; + break; + + // + case X_BAR_PATTERN_FLAG: + result = "XFLAGP"; + break; + + // + case X_BAR_PATTERN_SIGNALKEY: + result = "XSIGNALKEYP"; + break; + + // + case X_BAR_PATTERN_OB: + result = "XOBP"; + break; + + // + case X_BAR_PATTERN_FVG: + result = "XFVGP"; + break; + + // + case X_BAR_PATTERN_SUPPORT: + result = "XSUPPORTP"; + break; + + // + case X_BAR_PATTERN_RESISTANCE: + result = "XRESISTANCEP"; + break; + + // + case X_BAR_PATTERN_PULLBACK: + result = "XPULLBACKP"; + break; + + // + case X_BAR_PATTERN_CONSOLIDATION: + result = "XCONSOLIDATIONP"; + break; + + // + case X_BAR_PATTERN_LEG: + result = "XLEGP"; + break; + } + + // + return result; +} + +/** + * Parse an String Representation to it's Corresponding Bar Pattern ENUM ... + * + * @param value: string, provided pattern's string ... + * + * @return ( ENUM_X_BAR_PATTERN ) + */ +ENUM_X_BAR_PATTERN ToBarPattern(string value) +{ + // + ENUM_X_BAR_PATTERN result = X_BAR_PATTERN_NONE; + + // + // Validate ... + if (!IsXValid(value)) + { + return result; + } + + // + if (value == ToXString(X_BAR_PATTERN_NONE)) + { + result = X_BAR_PATTERN_NONE; + } + else if (value == ToXString(X_BAR_PATTERN_HIGH)) + { + result = X_BAR_PATTERN_HIGH; + } + else if (value == ToXString(X_BAR_PATTERN_LOW)) + { + result = X_BAR_PATTERN_LOW; + } + else if (value == ToXString(X_BAR_PATTERN_MOMENTUM)) + { + result = X_BAR_PATTERN_MOMENTUM; + } + else if (value == ToXString(X_BAR_PATTERN_ENGULFED)) + { + result = X_BAR_PATTERN_ENGULFED; + } + else if (value == ToXString(X_BAR_PATTERN_TRUE_GAPED)) + { + result = X_BAR_PATTERN_TRUE_GAPED; + } + else if (value == ToXString(X_BAR_PATTERN_PINNED)) + { + result = X_BAR_PATTERN_PINNED; + } + else if (value == ToXString(X_BAR_PATTERN_STAR)) + { + result = X_BAR_PATTERN_STAR; + } + else if (value == ToXString(X_BAR_PATTERN_PIERCING)) + { + result = X_BAR_PATTERN_PIERCING; + } + else if (value == ToXString(X_BAR_PATTERN_RISING)) + { + result = X_BAR_PATTERN_RISING; + } + else if (value == ToXString(X_BAR_PATTERN_FLAG)) + { + result = X_BAR_PATTERN_FLAG; + } + else if (value == ToXString(X_BAR_PATTERN_SIGNALKEY)) + { + result = X_BAR_PATTERN_SIGNALKEY; + } + else if (value == ToXString(X_BAR_PATTERN_OB)) + { + result = X_BAR_PATTERN_OB; + } + else if (value == ToXString(X_BAR_PATTERN_FVG)) + { + result = X_BAR_PATTERN_FVG; + } + else if (value == ToXString(X_BAR_PATTERN_SUPPORT)) + { + result = X_BAR_PATTERN_SUPPORT; + } + else if (value == ToXString(X_BAR_PATTERN_RESISTANCE)) + { + result = X_BAR_PATTERN_RESISTANCE; + } + else if (value == ToXString(X_BAR_PATTERN_PULLBACK)) + { + result = X_BAR_PATTERN_PULLBACK; + } + else if (value == ToXString(X_BAR_PATTERN_CONSOLIDATION)) + { + result = X_BAR_PATTERN_CONSOLIDATION; + } + else if (value == ToXString(X_BAR_PATTERN_LEG)) + { + result = X_BAR_PATTERN_LEG; + } + + // + return result; +} + +/** + * Get All Available Valid Bar Patterns ... + * + * @param dest: ENUM_X_BAR_PATTERN, reference collection to fill ... + * + * @return ( int ) + */ +int GetAllBarPatters(ENUM_X_BAR_PATTERN &dest[]) +{ + // + XClean(dest); + + // + Add(X_BAR_PATTERN_HIGH, dest); + Add(X_BAR_PATTERN_LOW, dest); + Add(X_BAR_PATTERN_MOMENTUM, dest); + Add(X_BAR_PATTERN_ENGULFED, dest); + Add(X_BAR_PATTERN_TRUE_GAPED, dest); + Add(X_BAR_PATTERN_PINNED, dest); + Add(X_BAR_PATTERN_STAR, dest); + Add(X_BAR_PATTERN_PIERCING, dest); + Add(X_BAR_PATTERN_RISING, dest); + Add(X_BAR_PATTERN_FLAG, dest); + Add(X_BAR_PATTERN_SIGNALKEY, dest); + Add(X_BAR_PATTERN_OB, dest); + Add(X_BAR_PATTERN_FVG, dest); + Add(X_BAR_PATTERN_SUPPORT, dest); + Add(X_BAR_PATTERN_RESISTANCE, dest); + Add(X_BAR_PATTERN_PULLBACK, dest); + Add(X_BAR_PATTERN_CONSOLIDATION, dest); + Add(X_BAR_PATTERN_LEG, dest); + + // + return ArraySize(dest); +} + +/** + * Get All Available Valid Bar Patterns ... + * + * @param dest: ENUM_X_BAR_PATTERN, collection reference to Fill Patterns ... + * @param dir: ENUM_X_DIRECTION, collection reference to Fill Directions ... + * @param forDir: ENUM_X_DIRECTION, Force Patterns Direction ... + * + * @return ( int ) + */ +int GetAllBarPatters( + ENUM_X_BAR_PATTERN &dest[], + ENUM_X_DIRECTION &dir[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + XClean(dest); + XClean(dir); + + // + Add(X_BAR_PATTERN_HIGH, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_LOW, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_MOMENTUM, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_ENGULFED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_TRUE_GAPED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PINNED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_STAR, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PIERCING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_RISING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_FLAG, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_SIGNALKEY, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_OB, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_FVG, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_SUPPORT, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_RESISTANCE, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PULLBACK, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_CONSOLIDATION, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_LEG, dest); + Add(forDir, dir); + + // + return ArraySize(dest); +} + +/** + * Fill Required Candlestick Patters ... + * + * @param dest: ENUM_X_BAR_PATTERN, collection reference to Fill ... + * + * @return ( int ) + */ +int GetCandlestickPatterns(ENUM_X_BAR_PATTERN &dest[]) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + Add(X_BAR_PATTERN_STAR, dest); + Add(X_BAR_PATTERN_FLAG, dest); + Add(X_BAR_PATTERN_PINNED, dest); + Add(X_BAR_PATTERN_RISING, dest); + Add(X_BAR_PATTERN_MOMENTUM, dest); + Add(X_BAR_PATTERN_ENGULFED, dest); + Add(X_BAR_PATTERN_PIERCING, dest); + Add(X_BAR_PATTERN_SIGNALKEY, dest); + Add(X_BAR_PATTERN_TRUE_GAPED, dest); + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Fill Required Candlestick Patters ... + * + * @param dest: ENUM_X_BAR_PATTERN, collection reference to Fill Patterns ... + * @param dir: ENUM_X_DIRECTION, collection reference to Fill Directions ... + * @param forDir: ENUM_X_DIRECTION, Force Patterns Direction ... + * + * @return ( int ) + */ +int GetCandlestickPatterns( + ENUM_X_BAR_PATTERN &dest[], + ENUM_X_DIRECTION &dir[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + XClean(dir); + + // + Add(X_BAR_PATTERN_STAR, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_FLAG, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PINNED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_RISING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_MOMENTUM, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_ENGULFED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PIERCING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_SIGNALKEY, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_TRUE_GAPED, dest); + Add(forDir, dir); + + // + result = ArraySize(dest); + + // + return result; +} + +// +// Structures ... + +/** + * Model a Trend Line ... + **/ +struct XTrend +{ + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + double fromValue; + datetime fromTime; + + // + double toValue; + datetime toTime; + + // + ENUM_X_DIRECTION dir; + + // + // Constructor ... + XTrend() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _symbol: string, Specified Symbol ... + * @param _period: ENUM_TIMEFRAMES, Specified Period ... + * @param _time: datetime, Detection Time ... + * @param _fromValue: double, From Value ... + * @param _fromTime: datetime, From Time ... + * @param _toValue: double, To Value ... + * @param _toTime: datetime, To Time ... + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + datetime _time, + double _fromValue, + datetime _fromTime, + double _toValue, + datetime _toTime // + ) + { + // + bool result = false; + + // + time = _time; + symbol = _symbol; + period = _period; + toTime = _toTime; + toValue = _toValue; + fromTime = _fromTime; + fromValue = _fromValue; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + // Setting Direction ... + if (result) + { + // + dir = + fromValue < toValue + ? X_DIRECTION_BULLISH + : fromValue > toValue + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + return result; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + toValue = 0; + fromValue = 0; + symbol = NULL; + period = NULL; + toTime = NULL; + fromTime = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsXValid(time) && + IsXValid(symbol) && + IsXValid(period) && + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue) && + fromTime < toTime; + + // + return result; + } + + /** + * Check Trend Has Specific Direction ... + * + * @return ( bool ) + */ + bool HasTrend() + { + return IsValid() && + HasDirection(dir); + } + + /** + * Check Trend is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + return HasTrend() && + IsXBullish(dir); + } + + /** + * Check Trend is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + return HasTrend() && + IsXBearish(dir); + } + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetObjectID() + { + // + string result = NULL; + + // + if (IsValid()) + { + double ifv = NormalizePrice(fromValue, symbol); + result = "XTRND_" + ToXString(dir) + "_" + ToXString(ifv) + "_" + ToXString(TimeToSeconds(fromTime)); + } + + // + return result; + } +}; + +/** + * Represent a Pivot ... + **/ +struct XPivot +{ + // + // Props ... + double value; // Value + datetime time; // Time + string symbol; // Symbol + ENUM_X_DIRECTION dir; // Direction + ENUM_TIMEFRAMES period; // Period + ENUM_X_PIVOT_TYPE type; // Type + + // + string prefix; // Object Prefix + + // + // Constructor ... + XPivot() + { + Clean(); + } + + // + // Init ... + + /** + * Initialize Structure ... + * + * @param _value: double, value of point ... + * @param _time: datetime, time of point ... + * @param _symbol: string, Symbol ... + * @param _dir: ENUM_X_DIRECTION, direction of point ... + * @param _period: ENUM_TIMEFRAMES, period ... + * @param _type: ENUM_X_PIVOT_TYPE, point type ... + * + * @return ( bool ) + */ + bool Init( + double _value, + datetime _time, + string _symbol, + ENUM_X_DIRECTION _dir, + ENUM_TIMEFRAMES _period, + ENUM_X_PIVOT_TYPE _type // + ) + { + // + bool result = false; + + // + dir = _dir; + time = _time; + type = _type; + value = _value; + symbol = _symbol; + period = _period; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + value = 0; + time = NULL; + symbol = NULL; + period = NULL; + prefix = NULL; + dir = X_DIRECTION_NONE; + type = X_PIVOT_TYPE_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + value > 0 && + IsXValid(type) && + HasDirection(dir) && + IsSpecifiedValid(time) && + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period); + + // + return result; + } + + /** + * Check Model is Peak or not ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = + IsValid() && + IsXPeak(type); + + // + return result; + } + + /** + * Check Model is Vale or not ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = + IsValid() && + IsXVale(type); + + // + return result; + } + + /** + * Check Point is Bullish or not ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + IsSpecifiedBullish(dir); + + // + return result; + } + + /** + * Check Point is Bearish or not ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + IsSpecifiedBearish(dir); + + // + return result; + } + + /** + * Check two Struct are Same or not ... + * + * @param item: XPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XPivot &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + dir == item.dir && + type == item.type && + time == item.time && + value == item.value && + symbol == item.symbol && + period == item.period; + + // + if (result && IsXValid(prefix)) + { + // + result = + result && + prefix == item.prefix; + } + + // + return result; + } + + /** + * Calculate Pivot Age ... + * + * @return ( int ) + */ + int GetAge() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetBarIndex( + symbol, + period, + time // + ); + + // + return result; + } + + /** + * Get Pivot Time Bar ... + * + * @param bar: XOHCL, reference to hold result ... + * + * @return ( bool ) + */ + bool GetBar(XOHCL &bar) + { + // + bool result = false; + + // + // Prepare ... + bar.Clean(); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Initial Bar ... + result = bar.Init( + symbol, + period, + time // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + /** + * Check to model Has Same Symbol ... + * + * @param item: XPivot, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSameSymbolAs(XPivot &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + /** + * Check to model Has Same Period ... + * + * @param item: XPivot, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSamePeriodAs(XPivot &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + period == item.period; + + // + return result; + } + + /** + * Check to model Has Same Symbol/Period ... + * + * @param item: XPivot, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSameMarketAs(XPivot &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + IsSameSymbolAs(item) && + IsSamePeriodAs(item); + + // + return result; + } + + /** + * Check to model Has Same Type ... + * + * @param item: XPivot, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSameTypeAs(XPivot &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + type == item.type; + + // + return result; + } + + /** + * Check to model Has Same Direction ... + * + * @param item: XPivot, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSameDirectionAs(XPivot &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + dir == item.dir; + + // + return result; + } + + // + // Logging Tools ... + + /** + * Extract Specified Token of Struct ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + string token = GetToken(this); + + // + result = + (IsSpecifiedValid(prefix) + ? prefix + "_" + : "") + + token; + + // + return result; + } + + /** + * Represent an String Unique Identifier for Chart Objects ... + * + * @return ( string ) + */ + string GetObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time)); + + // + return result; + } + + /** + * Represent a Point as String ... + * + * @param spacer: string, How to Represent Spaces ... + * + * @return ( string ) + */ + string GetMessage(string spacer = NULL) + { + // + string result = ""; + + // + // Normalize Spacer ... + if (!IsSpecifiedValid(spacer)) + { + spacer = " "; + } + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + result = + ToXString(dir) + spacer + GetTag() + ":" + spacer + + "Symbol: " + symbol + spacer + + "Period: " + ToXString(period) + spacer + + "Type: " + ToXString(type) + spacer + + "Direction: " + ToXString(dir) + spacer + + "Value: " + ToXString(value) + spacer + + "Time: " + ToXString(time) + spacer; + + // + return result; + } +}; + +/** + * Model a Box ... + **/ +struct XBoxZone +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime at; + datetime from; + datetime to; + + // + string type; + ENUM_X_DIRECTION dir; + + // + // Special Props ... + datetime breakAt; + datetime tests[]; + datetime acteds[]; + datetime breaks[]; + datetime insides[]; + datetime refines[]; + datetime fakeBreaks[]; + + // + // 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; + + // + SpecialClean(); + + // + ZeroMemory(this); + } + + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + double _upper, + double _lower, + datetime _from, + datetime _to, + ENUM_X_DIRECTION _dir, + string _type = "", + datetime _at = NULL // + ) + { + // + bool result = false; + + // + // Validate ... + result = IsXValid(_symbol) && + IsXValid(_period) && + _upper > 0 && + _lower > 0 && + _upper > _lower && + IsXValid(_from) && + IsXValid(_to) && + _from < _to && + HasDirection(_dir); + if (!result) + { + return result; + } + + // + this.to = _to; + this.at = _at; + this.dir = _dir; + this.from = _from; + this.type = _type; + this.lower = _lower; + this.upper = _upper; + this.symbol = _symbol; + this.period = _period; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + /** + * Clean Special Props ... + */ + void SpecialClean() + { + // + breakAt = NULL; + XClean(tests); + XClean(acteds); + XClean(breaks); + XClean(insides); + XClean(refines); + XClean(fakeBreaks); + } + + /** + * 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; + } + + /** + * At Bar Index ... + * + * @return ( int ) + */ + int AtIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid() || !IsXValid(at)) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + at // + ); + + // + return result; + } + + /** + * Retrieve At Bar ... + * + * @return ( bool ) + */ + bool AtBar(XOHCL &bar) + { + // + bool result = false; + + // + bar.Clean(); + + // + int idx = AtIndex(); + + // + 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; + } +}; + +/** + * Model a Direction Shift ... + **/ +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; + } + + // + bool Init( + string _type, + datetime _at, + double _after, + double _before, + string _symbol, + ENUM_TIMEFRAMES _period, + ENUM_X_DIRECTION _shiftTo // + ) + { + // + bool result = false; + + // + // Validate ... + result = + IsXValid(_at) && + IsXValid(_type) && + IsXValid(_symbol) && + IsXValid(_period) && + NotEmptyZero(_after) && + NotEmptyZero(_before) && + HasDirection(_shiftTo); + if (!result) + { + return result; + } + + // + type = _type; + at = _at; + after = _after; + before = _before; + symbol = _symbol; + period = _period; + shiftTo = _shiftTo; + + // + result = IsValid(); + + // + 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; + } +}; + +/** + * Configure Draws ... + **/ +struct XPOIDrawConfig +{ + // + // Props ... + + // + color bullishColor; + color bearishColor; + color neuturalColor; + + // + int arrowsWidth; + int bullishArrow; + int bearishArrow; + int arrowsThreshold; + ENUM_X_PRICE arrowsValePriceType; + ENUM_X_PRICE arrowsPeakPriceType; + + // + int zonesWidth; + bool zonesFill; + bool ignoreZonesAt; + ENUM_LINE_STYLE zonesStyle; + + // + int trendWidth; + bool trendRayLeft; + bool trendRayRight; + ENUM_LINE_STYLE trendStyle; + + // + // Constructor ... + XPOIDrawConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + bullishColor = CLR_NONE; + bearishColor = CLR_NONE; + neuturalColor = CLR_NONE; + + // + arrowsWidth = 0; + bullishArrow = 0; + bearishArrow = 0; + arrowsThreshold = 0; + arrowsValePriceType = X_PRICE_NONE; + arrowsPeakPriceType = X_PRICE_NONE; + + // + zonesWidth = 1; + zonesFill = false; + ignoreZonesAt = true; + zonesStyle = STYLE_SOLID; + + // + trendWidth = 0; + trendRayLeft = false; + trendRayRight = false; + trendStyle = STYLE_DOT; + } + + /** + * Default Config ... + */ + void Default() + { + // + bullishColor = clrAqua; + bearishColor = clrMagenta; + neuturalColor = clrGray; + + // + arrowsWidth = 1; + bullishArrow = 159; + bearishArrow = 159; + arrowsThreshold = 5; + arrowsValePriceType = X_PRICE_LOW; + arrowsPeakPriceType = X_PRICE_HIGH; + + // + zonesWidth = 1; + zonesFill = true; + ignoreZonesAt = true; + zonesStyle = STYLE_SOLID; + + // + trendWidth = 2; + trendRayLeft = false; + trendRayRight = true; + trendStyle = STYLE_DOT; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/Libraries/x-saherelm.x-trade.lib.mq5 b/BKPS/14041018/Libraries/x-saherelm.x-trade.lib.mq5 new file mode 100644 index 0000000..57e740c --- /dev/null +++ b/BKPS/14041018/Libraries/x-saherelm.x-trade.lib.mq5 @@ -0,0 +1,6613 @@ +/////////////////////////////////////////////////////// +// +// 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 + bool doRFOnEntry; // Do RF on Entry + double actingDistance; // Acting Distances + double target; // Target Price for Actions + double volumeMultiplier; // Volume Multiplier for Partial Close + double tpValue; // TP Value Changed ... + + // + // Constructor ... + XTarget() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + target = 0; + tpValue = 0; + doRF = false; + actingDistance = 0; + doRFOnEntry = 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; + } + + // + bool IsLong() + { + return IsValid() && + IsXBullish(type); + } + + // + bool IsBullish() + { + return IsLong(); + } + + // + bool IsShort() + { + return IsValid() && + IsXBearish(type); + } + + // + bool IsBearish() + { + return IsShort(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + return IsBullish() + ? X_DIRECTION_BULLISH + : IsBearish() + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // 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(); + 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(); + 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; + } + + // + string GetObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = "XSignal_" + + symbol + "_" + + ToXString(period) + "_" + + ToXString(type) + "_" + + ToXString(TimeToSeconds(time)); + + // + 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 name; // Provider Name + 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() + { + // + name = NULL; + 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 _name, + 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); + + // + name = _name; + 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() && + name == dest.name && + symbol == dest.symbol && + period == dest.period; + + // + return result; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + IsSpecifiedValid(name) && + 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[], + XPosition &positions[], + int barIndex = 0 // +); + +// +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; +} + +// +bool IsXBullish(ENUM_POSITION_TYPE type) +{ + return type == POSITION_TYPE_BUY; +} + +// +bool IsXBullish(ENUM_X_POSITION_TYPES type) +{ + return type == X_POSITION_TYPE_LONG; +} + +// +bool IsXBearish(ENUM_POSITION_TYPE type) +{ + return type == POSITION_TYPE_SELL; +} + +// +bool IsXBearish(ENUM_X_POSITION_TYPES type) +{ + return type == X_POSITION_TYPE_SHORT; +} + +// +// 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 || + Contains(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 // + ); + + // + // Compare TP with Targets ... + int idx = IsLong(signal.type) + ? GetHighest(targets) + : GetLowest(targets); + has = IsValidIndex(idx); + if (has) + { + // + // Compare TP ... + has = IsLong(signal.type) + ? targets[idx].target > signal.tp + : targets[idx].target < signal.tp; + if (has) + { + // + XTarget tpTarget; + tpTarget = targets[idx]; + tpTarget.actingDistance = 0; + tpTarget.target = signal.tp; + + // + signal.tp = targets[idx].target; + targets[idx].actingDistance = 0; + + // + ArrayRemove( + targets, + idx, + 1 // + ); + + // + AddRef( + tpTarget, + targets // + ); + } + + // + // 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/14041018/MQL5.code-workspace b/BKPS/14041018/MQL5.code-workspace new file mode 100644 index 0000000..cb10755 --- /dev/null +++ b/BKPS/14041018/MQL5.code-workspace @@ -0,0 +1,21 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "C_Cpp.default.includePath": [ + "c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include\\Include", + "c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include", + "c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\572C4A1F743028C65C8BA0B780030F0D\\MQL5\\Include", + "c:\\Users\\saherelm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include" + ], + "C_Cpp.clang_format_style": "{ BasedOnStyle: Microsoft, UseTab: Never, IndentWidth: 4, TabWidth: 4, ColumnLimit: 0}", + "files.associations": { + "*.mq5": "cpp", + "*.mqh": "cpp", + "*.ex5": "cpp" + } + } +} diff --git a/BKPS/14041018/README.md b/BKPS/14041018/README.md new file mode 100644 index 0000000..31dbde1 --- /dev/null +++ b/BKPS/14041018/README.md @@ -0,0 +1,11 @@ +# MQL5 + +this is a workspace which contains MetaTrader4 Data Folder Contents to Directly develop MQL5 using VSCode and test them. + +## Maintainer + +Hadi Khazaee asl + +[https://www.saherelm.ir](https://www.saherelm.ir) + +[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com) diff --git a/BKPS/14041018/X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 b/BKPS/14041018/X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 new file mode 100644 index 0000000..cbc969e --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 @@ -0,0 +1,621 @@ + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int scoreBullish = 0; + int scoreBearish = 0; + bool isBullish = false; + bool isBearish = false; + int barIndex = bar.Index() + 1; + + // + // Initialize Indexed Bar ... + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // #region Reading Conditions and Scoring ... + // + // ATR ... + bool isATRUp = kiParser.IsVolatilityHigh(barIndex) || + kiParser.IsVolatilitySwitchdToHigh(barIndex); + + // #region KI ... + // + bool isKIReadyForBullish = ((kiParser.IsKIFastBearish(barIndex) || + (kiParser.IsKIFastBullish(barIndex) && + iBar.IsRejected(kiHelper.GetKIFast(barIndex), X_DIRECTION_BULLISH))) && + kiParser.IsKISlowBullish(barIndex)); + + // + bool isKIReadyForBearish = ((kiParser.IsKIFastBullish(barIndex) || + (kiParser.IsKIFastBearish(barIndex) && + iBar.IsRejected(kiHelper.GetKIFast(barIndex), X_DIRECTION_BEARISH))) && + kiParser.IsKISlowBearish(barIndex)); + + // + bool isKIBandBullish = (kiHelper.GetKIUpper(barIndex) > kiHelper.GetKIUpper(barIndex + 1) || + kiHelper.GetKILower(barIndex) > kiHelper.GetKILower(barIndex + 1)); + + // + bool isKIBandBearish = (kiHelper.GetKIUpper(barIndex) < kiHelper.GetKIUpper(barIndex + 1) || + kiHelper.GetKILower(barIndex) < kiHelper.GetKILower(barIndex + 1)); + + // + bool isKIBullish = (kiParser.IsKIFastBullish(barIndex) || + kiParser.IsKIFastSwitchedToBullish(barIndex)) && + (kiParser.IsKISlowBullish(barIndex) || + kiParser.IsKISlowSwitchedToBullish(barIndex)); + if (isKIBullish) + { + scoreBullish++; + } + + // + bool isKIBearish = (kiParser.IsKIFastBearish(barIndex) || + kiParser.IsKIFastSwitchedToBearish(barIndex)) && + (kiParser.IsKISlowBearish(barIndex) || + kiParser.IsKISlowSwitchedToBearish(barIndex)); + if (isKIBearish) + { + scoreBearish++; + } + // #endregion + + // #region KI Wave ... + // + bool isKIWaveBullish = kiParser.IsKIWaveBullish(barIndex) || + kiParser.IsKIWaveSwitchedToBullish(barIndex); + if (isKIWaveBullish) + { + scoreBullish++; + } + + // + bool isKIWaveBearish = kiParser.IsKIWaveBearish(barIndex) || + kiParser.IsKIWaveSwitchedToBearish(barIndex); + if (isKIWaveBearish) + { + scoreBearish++; + } + // #endregion + + // #region MA ... + // + bool isMaBullish = kiParser.IsMACrossoverBullish(barIndex) || + kiParser.IsMACrossoverSwitchedToBullish(barIndex); + if (isMaBullish) + { + scoreBullish++; + } + + // + bool isMaBearish = kiParser.IsMACrossoverBearish(barIndex) || + kiParser.IsMACrossoverSwitchedToBearish(barIndex); + if (isMaBearish) + { + scoreBearish++; + } + // #endregion + + // #region LowerTF Candlstick ... + // + bool isLowerTFBullish = IsTFBullishPattern(barIndex, PERIOD_M5); + if (isLowerTFBullish) + { + scoreBullish++; + } + + // + bool isLowerTFBearish = IsTFBearishPattern(barIndex, PERIOD_M5); + if (isLowerTFBearish) + { + scoreBearish++; + } + // #endregion + + // #region Candlestick ... + // + bool isCandlestickBullish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BULLISH // + ); + if (isCandlestickBullish) + { + scoreBullish++; + } + + // + bool isCandlestickBearish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BEARISH // + ); + if (isCandlestickBearish) + { + scoreBearish++; + } + // #endregion + // #endregion + + // #region Summarize Directional Conditions ... + // + isBullish = + isATRUp && + isLowerTFBullish && + isKIReadyForBullish && + isCandlestickBullish && + scoreBullish >= 2 && + (isKIBullish || + isMaBullish || + isKIWaveBullish || + isKIBandBullish); + + // + isBearish = + isATRUp && + isLowerTFBearish && + isKIReadyForBearish && + isCandlestickBearish && + scoreBearish >= 2 && + (isKIBearish || + isMaBearish || + isKIWaveBearish || + isKIBandBearish); + // #endregion + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Select Operational Zone ... + if (isBullish) + { + // + // Looking Bar Patterns to Detect Zone ... + poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BULLISH); + } + else if (isBearish) + { + // + // Looking Bar Patterns to Detect Zone ... + poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BEARISH); + } + + // + // Refactor Result ... + result = result && + zone.IsValid(); + if (result) + { + // + // Refine Zone ... + poiDetector.RefineZone(zone); + + // + // SL Refactoring ... + + // + XOHCL toBar; + if (zone.ToBar(toBar)) + { + // + int to = zone.ToIndex(); + int from = zone.FromIndex(); + int length = from - to; + double iValue = + isBullish + ? toBar.FindLowest(length, MODE_LOW) + : isBearish + ? toBar.FindHighest(length, MODE_HIGH) + : EMPTY_VALUE; + if (NotEmptyZero(iValue)) + { + // + if (isBullish) + { + zone.lower = MathMin(zone.lower, iValue); + } + + // + if (isBearish) + { + zone.upper = MathMax(zone.upper, iValue); + } + } + } + toBar.Clean(); + } + + // + // Do Directional Validation ... + if (result) + { + // + // Bullish ... + if (isBullish) + { + // + isBullish = + isBullish && + isLowerTFBullish && + isCandlestickBullish; + } + + // + // Bearish ... + if (isBearish) + { + // + isBearish = + isBearish && + isLowerTFBearish && + isCandlestickBearish; + } + + // + result = isBullish || isBearish; + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate Result ... + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Draws ... + bool draw = true; + if (draw && result) + { + // + int drawn = 0; + + // + XPOIDrawConfig config; + config.Default(); + + // + if (zone.IsValid()) + { + // + drawn++; + + // + config.zonesWidth = 3; + config.bullishColor = clrYellow; + config.bearishColor = clrOrange; + + // + poiDrawer.DrawZone(zone, config); + + // + config.Default(); + } + + // + config.Clean(); + + // + if (drawn > 0) + { + // DebugBreak(); + } + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = result && + HasDirection(dir); + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + if (result) + { + // + double upper = isBullish + ? entry + : zone.upper; + double lower = isBullish + ? zone.lower + : entry; + datetime to = bar.time; + datetime from = isBullish + ? zone.from + : zone.from; + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + +bool HasRecentPatternTouched( + XBoxZone &zone, + double price, + int barIndex = 0, + int loopback = 5, + int threshold = 5, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + // Validate ... + result = NotEmptyZero(price); + if (!result) + { + return result; + } + + // + // Normalize ... + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL iBar; + bool has = false; + int iBullishIDX = -1; + int iBearishIDX = -1; + bool isBullish = false; + bool isBearish = false; + XBoxZone iBullishZones[]; + XBoxZone iBearishZones[]; + XPatternAnalysis iAnalysis; + XPatternAnalysisConfig iConfig; + + // + // Preparing Pattern Analysis Config ... + iConfig.Default(); + + // + // Customize Patterns ... + // iConfig.FullPattern(); + + // + // iConfig.AddPattern(X_BAR_PATTERN_OB); + // iConfig.AddPattern(X_BAR_PATTERN_PINNED); + // iConfig.AddPattern(X_BAR_PATTERN_ENGULFED); + // iConfig.AddPattern(X_BAR_PATTERN_SIGNALKEY); + + // + // iConfig.AddPattern(X_BAR_PATTERN_FVG); + // iConfig.AddPattern(X_BAR_PATTERN_PIERCING); + + // + // iConfig.AddPattern(X_BAR_PATTERN_STAR); + // iConfig.AddPattern(X_BAR_PATTERN_RISING); + // iConfig.AddPattern(X_BAR_PATTERN_MOMENTUM); + // iConfig.AddPattern(X_BAR_PATTERN_CONSOLIDATION); + // iConfig.AddPattern(X_BAR_PATTERN_LOW, X_DIRECTION_BULLISH); + // iConfig.AddPattern(X_BAR_PATTERN_HIGH, X_DIRECTION_BEARISH); + // iConfig.AddPattern(X_BAR_PATTERN_SUPPORT); + // iConfig.AddPattern(X_BAR_PATTERN_RESISTANCE); + + // + // XAUUSD ... + iConfig.AddPattern(X_BAR_PATTERN_FVG); + iConfig.AddPattern(X_BAR_PATTERN_PIERCING); + + // + // Looping Back ... + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Initialize Bar ... + has = iBar.Init(symbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Analyse Patterns ... + has = AnalyseBarPatterns(iBar, iAnalysis, iConfig); + if (!has) + { + // + iBar.Clean(); + continue; + } + + // + // Bullish ... + has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH); + has = HasChild(iBullishZones); + if (has) + { + // + has = HasNearZone( + iBullishIDX, + price, + threshold, + iBullishZones // + ); + if (has) + { + isBullish = true; + } + } + } + + // + // Bearish ... + has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH); + has = HasChild(iBearishZones); + if (has) + { + // + has = HasNearZone( + iBearishIDX, + price, + threshold, + iBearishZones // + ); + if (has) + { + isBearish = true; + } + } + } + + // + // Summarizing Result ... + has = + HasDirection(forDir) + ? (isBullish && !isBearish && IsXBullish(forDir)) || + (isBearish && !isBullish && IsXBearish(forDir)) + : (isBullish && !isBearish) || (isBearish && !isBullish); + if (has) + { + // + // Fill Zones ... + if (isBullish) + { + zone = iBullishZones[iBullishIDX]; + } + else + { + zone = iBearishZones[iBearishIDX]; + } + break; + } + + // + // Cleanup Resource ... + iBar.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iConfig.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + + // + return result; + } + + +// +// XAUUSD ... + +// // +// // FVG ... +// Add(X_BAR_PATTERN_FVG, patterns); +// Add(X_DIRECTION_NONE, patternsDir); + +// // +// // Piercing ... +// Add(X_BAR_PATTERN_PIERCING, patterns); +// Add(X_DIRECTION_NONE, patternsDir); + diff --git a/BKPS/14041018/X121XKIEA/Backup/x-ki.parser.conditions.tester.bkp.mq5 b/BKPS/14041018/X121XKIEA/Backup/x-ki.parser.conditions.tester.bkp.mq5 new file mode 100644 index 0000000..ddda3ef --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Backup/x-ki.parser.conditions.tester.bkp.mq5 @@ -0,0 +1,489 @@ +// #region KI Fast ... +// +// if (kiParser.IsKIFastBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastSwitchedToBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastSwitchedToBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastSameAsLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIFastSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region KI Slow ... +// +// if (kiParser.IsKISlowBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowSwitchedToBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowSwitchedToBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowSameAsLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISlowSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region KI Super Slow ... +// +// if (kiParser.IsKISuperSlowBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowSwitchedToBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowSwitchedToBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowSameAsLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKISuperSlowSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region KI Wave ... +// +// if (kiParser.IsKIWaveBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveSwitchedToBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveSwitchedToBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsKIWaveSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region KI Band ... +// +// if (kiParser.IsPriceOverKIUpper(barIndex, X_PRICE_LOW)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceSwitchedOverKIUpper(barIndex, X_PRICE_LOW)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceUnderKIUpper(barIndex, X_PRICE_HIGH)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceSwitchedUnderKIUpper(barIndex, X_PRICE_HIGH)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceOverKILower(barIndex, X_PRICE_LOW)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceSwitchedOverKILower(barIndex, X_PRICE_LOW)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceUnderKILower(barIndex, X_PRICE_HIGH)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceSwitchedUnderKILower(barIndex, X_PRICE_HIGH)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPriceInsideKIBands(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } +// #endregion + +// #region MA ... +// #region MA Fast ... +// +// if (kiParser.IsMAFastBullish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastSwitchedToBullish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastBearish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastSwitchedToBearish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMAFastSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region MA Slow ... +// +// if (kiParser.IsMASlowBullish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowSwitchedToBullish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowBearish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowSwitchedToBearish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASlowSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region MA Super Slow ... +// +// if (kiParser.IsMASuperSlowBullish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowSwitchedToBullish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowBearish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowSwitchedToBearish(barIndex, X_PRICE_CLOSE)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowSwitchedOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMASuperSlowSwitchedUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// +// if (kiParser.IsMACrossoverBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMACrossoverSwitchedToBullish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMACrossoverBearish(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsMACrossoverSwitchedToBearish(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + +// #region PV ... +// +// if (kiParser.IsPeakSameAsLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPeakOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsPeakUnderLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsValeSameAsLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsValeOverLast(barIndex)) +// { +// DebugBreak(); +// } + +// +// if (kiParser.IsValeUnderLast(barIndex)) +// { +// DebugBreak(); +// } +// #endregion + + diff --git a/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 new file mode 100644 index 0000000..a080e84 --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 @@ -0,0 +1,2584 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Parser Class Library +// ---------------------------------------------------- +// Name: XCX121XKIHelperParser +// Description: provides all Indicator +// Helper Parse requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.x121.xki.helper.mq5" + +// +// Definitions ... + +// +// Implementation ... + +class XCX121XKIHelperParser : XCBase +{ + // + // Public ... + public: + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XCX121XKIHelperParser(XCX121XKIHelper *_helper) + { + // + helper = _helper; + symbol = _helper.GetSymbol(); + period = _helper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCX121XKIHelperParser() + { + ZeroMemory(helper); + } + + // + // Tools ... + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = helper != NULL && + helper.IsValid() && + IsXValid(symbol) && + IsXValid(period); + + // + return result; + } + + /** + * Normalize Bar Index ... + * + * @param barIndex: int, Provided Bar Index ... + * + * @return ( int ) + */ + int NormalizeBarIndex(int barIndex = 0) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = helper.NormalizeBarIndex(barIndex); + + // + return result; + } + + // + // Parsers ... + // Indicators Base Conditions ... + + // #region KI Fast ... + bool IsKIFastBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKIFastState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsKIFastBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKIFastState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsKIFastSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIFastBullish(barIndex) && + !IsKIFastBullish(barIndex + 1); + + // + return result; + } + + bool IsKIFastSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIFastBearish(barIndex) && + !IsKIFastBearish(barIndex + 1); + + // + return result; + } + + bool IsKIFastOverLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKIFast(barIndex); + double pValue = helper.GetKIFast(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value >= pValue + distance; + + // + return result; + } + + bool IsKIFastUnderLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKIFast(barIndex); + double pValue = helper.GetKIFast(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value <= pValue - distance; + + // + return result; + } + + bool IsKIFastSameAsLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + helper.GetKIFast(barIndex) == helper.GetKIFast(barIndex + 1); + + // + return result; + } + + bool IsKIFastSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKIFastOverLast(barIndex) && + !IsKIFastOverLast(barIndex + 1); + if (!result) + { + return result; + } + + // + return result; + } + + bool IsKIFastSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKIFastUnderLast(barIndex) && + !IsKIFastUnderLast(barIndex + 1); + if (!result) + { + return result; + } + + // + return result; + } + // #endregion + + // #region KI Slow ... + bool IsKISlowBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKISlowState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsKISlowBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKISlowState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsKISlowSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKISlowBullish(barIndex) && + !IsKISlowBullish(barIndex + 1); + + // + return result; + } + + bool IsKISlowSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKISlowBearish(barIndex) && + !IsKISlowBearish(barIndex + 1); + + // + return result; + } + + bool IsKISlowOverLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKISlow(barIndex); + double pValue = helper.GetKISlow(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value >= pValue + distance; + + // + return result; + } + + bool IsKISlowUnderLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKISlow(barIndex); + double pValue = helper.GetKISlow(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value <= pValue - distance; + + // + return result; + } + + bool IsKISlowSameAsLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + helper.GetKISlow(barIndex) == helper.GetKISlow(barIndex + 1); + + // + return result; + } + + bool IsKISlowSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKISlowOverLast(barIndex) && + !IsKISlowOverLast(barIndex + 1); + if (!result) + { + return result; + } + + // + return result; + } + + bool IsKISlowSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKISlowUnderLast(barIndex) && + !IsKISlowUnderLast(barIndex + 1); + if (!result) + { + return result; + } + + // + return result; + } + // #endregion + + // #region KI Super Slow ... + bool IsKISuperSlowBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKISuperSlowState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsKISuperSlowBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKISuperSlowState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsKISuperSlowSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKISuperSlowBullish(barIndex) && + !IsKISuperSlowBullish(barIndex + 1); + + // + return result; + } + + bool IsKISuperSlowSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKISuperSlowBearish(barIndex) && + !IsKISuperSlowBearish(barIndex + 1); + + // + return result; + } + + bool IsKISuperSlowOverLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKISuperSlow(barIndex); + double pValue = helper.GetKISuperSlow(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value >= pValue + distance; + + // + return result; + } + + bool IsKISuperSlowUnderLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKISuperSlow(barIndex); + double pValue = helper.GetKISuperSlow(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value <= pValue - distance; + + // + return result; + } + + bool IsKISuperSlowSameAsLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + helper.GetKISuperSlow(barIndex) == helper.GetKISuperSlow(barIndex + 1); + + // + return result; + } + + bool IsKISuperSlowSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKISuperSlowOverLast(barIndex) && + !IsKISuperSlowOverLast(barIndex + 1); + if (!result) + { + return result; + } + + // + return result; + } + + bool IsKISuperSlowSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKISuperSlowUnderLast(barIndex) && + !IsKISuperSlowUnderLast(barIndex + 1); + if (!result) + { + return result; + } + + // + return result; + } + // #endregion + + // #region KI Wave ... + bool IsKIWaveBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetKIWaveState(barIndex) >= 1; + + // + return result; + } + + bool IsKIWaveBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetKIWaveState(barIndex) <= -1; + + // + return result; + } + + bool IsKIWaveSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIWaveBullish(barIndex) && + !IsKIWaveBullish(barIndex + 1); + + // + return result; + } + + bool IsKIWaveSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIWaveBearish(barIndex) && + !IsKIWaveBearish(barIndex + 1); + + // + return result; + } + + bool IsKIWaveOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + helper.GetKIWave(barIndex) > helper.GetKIWave(barIndex + 1); + + // + return result; + } + + bool IsKIWaveUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + helper.GetKIWave(barIndex) < helper.GetKIWave(barIndex + 1); + + // + return result; + } + + bool IsKIWaveSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKIWaveOverLast(barIndex) && + !IsKIWaveOverLast(barIndex + 1); + + // + return result; + } + + bool IsKIWaveSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsKIWaveUnderLast(barIndex) && + !IsKIWaveUnderLast(barIndex + 1); + + // + return result; + } + // #endregion + + // #region KI Band ... + bool IsPriceOverKIUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price > helper.GetKIUpper(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceUnderKIUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetKIUpper(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceOverKILower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price > helper.GetKILower(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceUnderKILower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetKILower(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceInsideKIBands( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetKIUpper(barIndex) && + price > helper.GetKILower(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceSwitchedOverKIUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsPriceOverKIUpper(barIndex, priceType) && + !IsPriceOverKIUpper(barIndex + 1, priceType); + + // + return result; + } + + bool IsPriceSwitchedUnderKIUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsPriceUnderKIUpper(barIndex, priceType) && + !IsPriceUnderKIUpper(barIndex + 1, priceType); + + // + return result; + } + + bool IsPriceSwitchedOverKILower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsPriceOverKILower(barIndex, priceType) && + !IsPriceOverKILower(barIndex + 1, priceType); + + // + return result; + } + + bool IsPriceSwitchedUnderKILower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsPriceUnderKILower(barIndex, priceType) && + !IsPriceUnderKILower(barIndex + 1, priceType); + + // + return result; + } + // #endregion + + // #region MA Fast/Slow/SuperSlow ... + + // #region MA Fast ... + bool IsMAFastBullish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL iBar; + result = IsValid() && + iBar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = iBar.GetPrice(priceType) > helper.GetMAFast(barIndex); + + // + iBar.Clean(); + + // + return result; + } + + bool IsMAFastBearish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL iBar; + result = IsValid() && + iBar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = iBar.GetPrice(priceType) < helper.GetMAFast(barIndex); + + // + iBar.Clean(); + + // + return result; + } + + bool IsMAFastOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetMAFast(barIndex) > helper.GetMAFast(barIndex + 1); + + // + return result; + } + + bool IsMAFastUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetMAFast(barIndex) < helper.GetMAFast(barIndex + 1); + + // + return result; + } + + bool IsMAFastSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsMAFastOverLast(barIndex) && + !IsMAFastOverLast(barIndex + 1); + + // + return result; + } + + bool IsMAFastSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsMAFastUnderLast(barIndex) && + !IsMAFastUnderLast(barIndex + 1); + + // + return result; + } + + bool IsMAFastSwitchedToBullish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsMAFastBullish(barIndex) && + !IsMAFastBullish(barIndex + 1); + + // + return result; + } + + bool IsMAFastSwitchedToBearish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsMAFastBearish(barIndex) && + !IsMAFastBearish(barIndex + 1); + + // + return result; + } + // #endregion + + // #region MA Slow ... + bool IsMASlowBullish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL iBar; + result = IsValid() && + iBar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = iBar.GetPrice(priceType) > helper.GetMASlow(barIndex); + + // + iBar.Clean(); + + // + return result; + } + + bool IsMASlowBearish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL iBar; + result = IsValid() && + iBar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = iBar.GetPrice(priceType) < helper.GetMASlow(barIndex); + + // + iBar.Clean(); + + // + return result; + } + + bool IsMASlowOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetMASlow(barIndex) > helper.GetMASlow(barIndex + 1); + + // + return result; + } + + bool IsMASlowUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetMASlow(barIndex) < helper.GetMASlow(barIndex + 1); + + // + return result; + } + + bool IsMASlowSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsMASlowOverLast(barIndex) && + !IsMASlowOverLast(barIndex + 1); + + // + return result; + } + + bool IsMASlowSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsMASlowUnderLast(barIndex) && + !IsMASlowUnderLast(barIndex + 1); + + // + return result; + } + + bool IsMASlowSwitchedToBullish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsMASlowBullish(barIndex) && + !IsMASlowBullish(barIndex + 1); + + // + return result; + } + + bool IsMASlowSwitchedToBearish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsMASlowBearish(barIndex) && + !IsMASlowBearish(barIndex + 1); + + // + return result; + } + // #endregion + + // #region MA Super Slow ... + bool IsMASuperSlowBullish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL iBar; + result = IsValid() && + iBar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = iBar.GetPrice(priceType) > helper.GetMASuperSlow(barIndex); + + // + iBar.Clean(); + + // + return result; + } + + bool IsMASuperSlowBearish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL iBar; + result = IsValid() && + iBar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = iBar.GetPrice(priceType) < helper.GetMASuperSlow(barIndex); + + // + iBar.Clean(); + + // + return result; + } + + bool IsMASuperSlowOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetMASuperSlow(barIndex) > helper.GetMASuperSlow(barIndex + 1); + + // + return result; + } + + bool IsMASuperSlowUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetMASuperSlow(barIndex) < helper.GetMASuperSlow(barIndex + 1); + + // + return result; + } + + bool IsMASuperSlowSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsMASuperSlowOverLast(barIndex) && + !IsMASuperSlowOverLast(barIndex + 1); + + // + return result; + } + + bool IsMASuperSlowSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsMASuperSlowUnderLast(barIndex) && + !IsMASuperSlowUnderLast(barIndex + 1); + + // + return result; + } + + bool IsMASuperSlowSwitchedToBullish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsMASuperSlowBullish(barIndex) && + !IsMASuperSlowBullish(barIndex + 1); + + // + return result; + } + + bool IsMASuperSlowSwitchedToBearish( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsMASuperSlowBearish(barIndex) && + !IsMASuperSlowBearish(barIndex + 1); + + // + return result; + } + // #endregion + + bool IsMACrossoverBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetMAFast(barIndex) > helper.GetMASlow(barIndex); + return result; + } + + bool IsMACrossoverBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetMAFast(barIndex) < helper.GetMASlow(barIndex); + return result; + } + + bool IsMACrossoverSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsMACrossoverBullish(barIndex) && + !IsMACrossoverBullish(barIndex + 1); + return result; + } + + bool IsMACrossoverSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsMACrossoverBearish(barIndex) && + !IsMACrossoverBearish(barIndex + 1); + return result; + } + // #endregion + + // #region PV ... + bool IsPeakSameAsLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetPeak(barIndex) == helper.GetPeak(barIndex + 1); + + // + return result; + } + + bool IsPeakOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetPeak(barIndex) > helper.GetPeak(barIndex + 1); + + // + return result; + } + + bool IsPeakUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetPeak(barIndex) < helper.GetPeak(barIndex + 1); + + // + return result; + } + + int CountSamePeaks( + int barIndex = 0, + int loopback = 10 // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + loopback = NormalizeInt(loopback, 2); + barIndex = NormalizeBarIndex(barIndex); + + // + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + if (IsPeakSameAsLast(i)) + { + result++; + } + } + + // + return result; + } + + bool IsValeSameAsLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetVale(barIndex) == helper.GetVale(barIndex + 1); + + // + return result; + } + + bool IsValeOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetVale(barIndex) > helper.GetVale(barIndex + 1); + + // + return result; + } + + bool IsValeUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetVale(barIndex) < helper.GetVale(barIndex + 1); + + // + return result; + } + + int CountSameVales( + int barIndex = 0, + int loopback = 10 // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + loopback = NormalizeInt(loopback, 2); + barIndex = NormalizeBarIndex(barIndex); + + // + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + if (IsValeSameAsLast(i)) + { + result++; + } + } + + // + return result; + } + // #endregion + + // #region ATR ... + bool IsATRBreakoutUp( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price > helper.GetATRRawUpper(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsATRBreakoutDown( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetATRRawLower(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsATROverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetATR(barIndex) > helper.GetATR(barIndex + 1); + + // + return result; + } + + bool IsATRUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + helper.GetATR(barIndex) < helper.GetATR(barIndex + 1); + + // + return result; + } + + bool IsATRSwitchedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsATROverLast(barIndex) && + !IsATROverLast(barIndex + 1); + + // + return result; + } + + bool IsATRSwitchedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsATRUnderLast(barIndex) && + !IsATRUnderLast(barIndex + 1); + + // + return result; + } + + bool IsVolatilityHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double atr = helper.GetATR(barIndex); + double atrMa = helper.GetATRSmoothed(barIndex); + result = atr > atrMa; + + // + return result; + } + + bool IsVolatilityLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double atr = helper.GetATR(barIndex); + double atrMa = helper.GetATRSmoothed(barIndex); + result = atr < atrMa; + + // + return result; + } + + bool IsVolatilitySwitchdToHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double atr = helper.GetATR(barIndex); + double atrPrev = helper.GetATR(barIndex + 1); + double atrMa = helper.GetATRSmoothed(barIndex); + double atrMaPrev = helper.GetATRSmoothed(barIndex + 1); + + // + result = + atr > atrMa && + atrPrev <= atrMaPrev; + + // + return result; + } + + bool IsVolatilitySwitchdToLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double atr = helper.GetATR(barIndex); + double atrPrev = helper.GetATR(barIndex + 1); + double atrMa = helper.GetATRSmoothed(barIndex); + double atrMaPrev = helper.GetATRSmoothed(barIndex + 1); + + // + result = + atr < atrMa && + atrPrev >= atrMaPrev; + + // + return result; + } + // #endregion + + // #region RSI ... + bool IsRSIBullish( + int barIndex = 0, + double threshold = 50 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) > threshold; + return result; + } + + bool IsRSIBearish( + int barIndex = 0, + double threshold = 50 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) < threshold; + return result; + } + + bool IsRSIOverbought( + int barIndex = 0, + double threshold = 70 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) > threshold; + return result; + } + + bool IsRSIOversold( + int barIndex = 0, + double threshold = 30 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) < threshold; + return result; + } + + bool IsRSISwitchedToOverSold( + int barIndex = 0, + double threshold = 30 // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsRSIOversold(barIndex, threshold) && + !IsRSIOversold(barIndex + 1, threshold); + + // + return result; + } + + bool IsRSISwitchedFromOverSold( + int barIndex = 0, + double threshold = 30 // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + !IsRSIOversold(barIndex, threshold) && + IsRSIOversold(barIndex + 1, threshold); + + // + return result; + } + + bool IsRSISwitchedToOverbought( + int barIndex = 0, + double threshold = 70 // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + IsRSIOverbought(barIndex, threshold) && + !IsRSIOverbought(barIndex + 1, threshold); + + // + return result; + } + + bool IsRSISwitchedFromOverbought( + int barIndex = 0, + double threshold = 70 // + ) + { + // + bool result = false; + + // + barIndex = NormalizeBarIndex(barIndex); + + // + result = + IsValid() && + !IsRSIOverbought(barIndex, threshold) && + IsRSIOverbought(barIndex + 1, threshold); + + // + return result; + } + + bool IsRSISwitchedToBullish( + int barIndex = 0, + double threshold = 50 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + IsRSIBullish(barIndex, threshold) && + !IsRSIBullish(barIndex + 1, threshold); + + // + return result; + } + + bool IsRSISwitchedToBearish( + int barIndex = 0, + double threshold = 50 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + IsRSIBearish(barIndex, threshold) && + !IsRSIBearish(barIndex + 1, threshold); + + // + return result; + } + // #endregion + + // #region Composite ... + // #endregion + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + XCX121XKIHelper *helper; + + // +}; + +// diff --git a/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 new file mode 100644 index 0000000..e8bb8e4 --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 @@ -0,0 +1,1727 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121XKISignaller ... +// Description: X121XKI 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 X121XKI Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.x121.xki.helper.mq5" +#include "../Classes/x-saherelm.x121.xki.parser.class.mq5" +#include "../Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.x121.xki.lib.mq5" + +// +// Implementation ... + +// +// Base X121XKI base Signaller ... +class XCX121XKIBaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + X121XKIInputs kiInputs; // X121XKI Inputs ... + XCX121XKIHelper *kiHelper; // X121XKI Indicator Helper ... + XCX121XKIPOIDrawer *poiDrawer; // X121XKI POI Drawer ... + XCX121XKIPOIDetector *poiDetector; // X121XKI POI Detector ... + XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ... + + // + // Constructor ... + XCX121XKIBaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + X121XKIInputs &_kiInputs, // X121XKIInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating X121XKI Indicator Helper Class ... + if (_kiInputs.IsValid()) + { + // + kiHelper = new XCX121XKIHelper(); + bool isInited = kiHelper.Init( + _symbol, + _period, + _kiInputs // + ); + if (isInited) + { + kiInputs = _kiInputs; + } + else + { + // + delete kiHelper; + ZeroMemory(kiHelper); + } + } + + // + // Instantiate X121XKI Helper Parser ... + kiParser = new XCX121XKIHelperParser(kiHelper); + + // + poiDrawer = new XCX121XKIPOIDrawer(); + poiDetector = new XCX121XKIPOIDetector(kiHelper, kiParser); + } + + // + // Deconstructor ... + ~XCX121XKIBaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + kiInputs.Clean(); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + delete kiHelper; + ZeroMemory(kiHelper); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = kiInputs.IsValid() && + kiHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// X121XKI Strategy 1 Signaller Class ... +class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCX121XKIStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + X121XKIInputs &_kiInputs, // X121XKIInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCX121XKIBaseSignaller("X121XKI1", + _symbol, + _period, + _kiInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + } + + // + // Deconstructor ... + ~XCX121XKIStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + iSignal.provider += "_" + iZone.type; + } + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + string provider = NULL; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Check Provided By Strategy 1 ... + provider = positions[i].provider; + StringReplace( + provider, + name, + "" // + ); + has = Contains(ToXString(X121_XKI_STRATEGY_1), positions[i].provider); + if (has) + { + // + // Now we Check Exit ... + // if (positions[i].IsLong()) + // { + // has = ExitBullishPOILong(); + // } + // else if (positions[i].IsShort()) + // { + // has = ExitBearishPOIShort(); + // } + + // // + // if (has) + // { + // } + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = true; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = false; + bool useSignaller5 = false; + bool useSignaller6 = false; + + // + XBoxZone tmpZone; + string provider = NULL; + ENUM_X_DIRECTION tmpDir; + + // + bool signaller1HasSignal = false; + bool signaller2HasSignal = false; + bool signaller3HasSignal = false; + bool signaller4HasSignal = false; + bool signaller5HasSignal = false; + bool signaller6HasSignal = false; + + // + // Validator Flags ... + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + + // + // Signal Checking ... + + // + // Signal Detection Flags ... + + // + // Signaller 1 ... + // POI ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += ToXString(X121_XKI_STRATEGY_1); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + // Breakout POI ... + if (useSignaller2) + { + // + signaller2HasSignal = Strategy2HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller2HasSignal) + { + // + provider += ToXString(X121_XKI_STRATEGY_2); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + // Reversal ... + if (useSignaller3) + { + // + signaller3HasSignal = Strategy3HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller3HasSignal) + { + // + provider += ToXString(X121_XKI_STRATEGY_3); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + // Continuation ... + if (useSignaller4) + { + // + signaller4HasSignal = Strategy4HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller4HasSignal) + { + // + provider += ToXString(X121_XKI_STRATEGY_4); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 5 ... + // Exhaustion ... + if (useSignaller5) + { + // + signaller5HasSignal = Strategy5HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller5HasSignal) + { + // + provider += ToXString(X121_XKI_STRATEGY_5); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 6 ... + // Trend Exhaustion ... + if (useSignaller6) + { + // + signaller6HasSignal = Strategy6HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller6HasSignal) + { + // + provider += ToXString(X121_XKI_STRATEGY_6); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal || + signaller5HasSignal || + signaller6HasSignal; + + // + // Signal Validating ... + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + if (result) + { + zone.type = "" + provider; + } + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Other Drawing Materials ... + XPOIDrawConfig drawConfig; + drawConfig.Default(); + + // + poiDrawer.DrawZone(zone, drawConfig); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + tmpZone.Clean(); + + // + return result; + } + + // #region Custom Signal Strategies ... + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int scoreBullish = 0; + int scoreBearish = 0; + bool isBullish = false; + bool isBearish = false; + int barIndex = bar.Index() + 1; + + // + // TEST ... + + + // + return false; + + // + // Initialize Indexed Bar ... + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // + XBoxZone swingLow; + XBoxZone swingHigh; + ENUM_X_DIRECTION patternsDir[]; + ENUM_X_BAR_PATTERN patterns[]; + poiDetector.FillStrategy1Patterns( + patterns, + patternsDir // + ); + + // + // Reading Swings ... + poiDetector.DetectRecentSwings( + swingHigh, + swingLow, + barIndex // + ); + + // + // Reading Order Flow ... + + // + // Bullish Order Flow ... + XBoxZone bullishOrderFlow[]; + int bullishOrderFlowRejectdIDX = -1; + poiDetector.HasOrderFlow(bullishOrderFlow, barIndex, 4, X_DIRECTION_BULLISH, 15); + + // + // Bearish Order Flow ... + XBoxZone bearishOrderFlow[]; + int bearishOrderFlowRejectdIDX = -1; + poiDetector.HasOrderFlow(bearishOrderFlow, barIndex, 4, X_DIRECTION_BEARISH, 15); + + // + // Base Conditions ... + + // + isBullish = + IsTFBullishPattern(barIndex, PERIOD_M1) && + IsTFBullishPattern(barIndex, PERIOD_M5) && + IsTFBullishPattern(barIndex, iBar.period) && + HasRejected( + bullishOrderFlowRejectdIDX, + iBar, + bullishOrderFlow // + ) && + poiDetector.HasRecentPatternRejected( + zone, + patterns, + patternsDir, + barIndex, + 3, // Loopback .. + iBar.period, + X_DIRECTION_BULLISH // + ); + if (!isBullish) + { + // + isBearish = + IsTFBearishPattern(barIndex, PERIOD_M1) && + IsTFBearishPattern(barIndex, PERIOD_M5) && + IsTFBearishPattern(barIndex, iBar.period) && + HasRejected( + bearishOrderFlowRejectdIDX, + iBar, + bearishOrderFlow // + ) && + poiDetector.HasRecentPatternRejected( + zone, + patterns, + patternsDir, + barIndex, + 3, // Loopback .. + iBar.period, + X_DIRECTION_BEARISH // + ); + } + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Count Touches ... + // int bullishTouches = 0; + // int bearishTouches = 0; + // if (result) + // { + // // + // kiParser.CountTouches( + // bullishTouches, + // bearishTouches, + // barIndex, + // 4 // Loopback ... + // ); + + // // + // isBullish = + // isBullish && + // bullishTouches >= bearishTouches; + + // // + // isBearish = + // isBearish && + // bearishTouches >= bullishTouches; + + // // + // // Summarize Result ... + // result = isBullish || isBearish; + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + + // // + // if (bullishTouches > 0 || bearishTouches > 0) + // { + // // DebugBreak(); + // } + // } + + // + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Do Directional Validation ... + if (result) + { + // + poiDetector.RefactorStrategy1OperationalZone(zone); + + // + // Bullish ... + if (isBullish) + { + // // + // isBullish = + // isBullish && + // isLowerTFBullish && + // isCandlestickBullish; + } + + // + // Bearish ... + if (isBearish) + { + // // + // isBearish = + // isBearish && + // isLowerTFBearish && + // isCandlestickBearish; + } + + // + result = isBullish || isBearish; + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Draws ... + bool draw = true; + if (draw && result) + { + // + int drawn = 0; + + // + poiDrawer.drawnObjects.Clear(); + + // + XPOIDrawConfig config; + config.Default(); + + // + if (zone.IsValid()) + { + // + drawn++; + + // + config.zonesWidth = 3; + config.bullishColor = clrYellow; + config.bearishColor = clrOrange; + + // + poiDrawer.DrawZone(zone, config); + + // + config.Default(); + } + + // + if (swingLow.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(swingLow, config); + } + + // + if (swingHigh.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(swingHigh, config); + } + + // + if (HasChild(bullishOrderFlow)) + { + // + drawn += ArraySize(bullishOrderFlow); + poiDrawer.DrawZones(bullishOrderFlow, config); + } + + // + if (HasChild(bearishOrderFlow)) + { + // + drawn += ArraySize(bearishOrderFlow); + poiDrawer.DrawZones(bearishOrderFlow, config); + } + + // + if (drawn > 0) + { + DebugBreak(); + return false; + } + + // + config.Clean(); + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = result && + HasDirection(dir); + if (result) + { + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + + // + double upper = isBullish + ? entry + : zone.upper; + double lower = isBullish + ? zone.lower + : entry; + datetime to = bar.time; + datetime from = isBullish + ? zone.from + : zone.from; + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + swingLow.Clean(); + XClean(patterns); + swingHigh.Clean(); + XClean(patternsDir); + XClean(bullishOrderFlow); + XClean(bearishOrderFlow); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * Breakout POI ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = false; + bool isBearish = false; + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Prepare Zone ... + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * Reversal ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = false; + bool isBearish = false; + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Prepare Zone ... + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * Continuation ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = false; + bool isBearish = false; + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Prepare Zone ... + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 5 ... + * Exhaustion ... + * + * @return ( bool ) + */ + bool Strategy5HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = false; + bool isBearish = false; + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Prepare Zone ... + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 6 ... + * Trend Exhaustion ... + * + * @return ( bool ) + */ + bool Strategy6HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = false; + bool isBearish = false; + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Prepare Zone ... + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + // #endregion + + // #region TF Patterns ... + bool IsTFBullishPattern( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL bar; + result = bar.Init(symbol, forPeriod, barIndex) && + poiDetector.HasCandlestickDirection(bar, X_DIRECTION_BULLISH); + bar.Clean(); + + // + return result; + } + + bool IsTFBearishPattern( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL bar; + result = bar.Init(symbol, forPeriod, barIndex) && + poiDetector.HasCandlestickDirection(bar, X_DIRECTION_BEARISH); + bar.Clean(); + + // + return result; + } + // #endregion + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 new file mode 100644 index 0000000..f115482 --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 @@ -0,0 +1,3489 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121XKIPoiDetector ... +// Description: X121XKI POI Detector 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 X121XKI POI Detector Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../../Helpers/x-saherelm.x121.xki.helper.mq5" +#include "../Classes/x-saherelm.x121.xki.parser.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCX121XKIPOIDetector : public XCMarketPatternDetector +{ + // + // Public ... + public: + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCX121XKIHelper *kiHelper; // X121XKI Helper ... + XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ... + + // + // Constructor ... + XCX121XKIPOIDetector( + XCX121XKIHelper *_kiHelper, + XCX121XKIHelperParser *_kiParser // + ) : XCMarketPatternDetector() + { + // + barAnalyser = new XCBarAnalyser(); + kiHelper = _kiHelper; + kiParser = _kiParser; + + // + symbol = kiHelper.GetSymbol(); + period = kiHelper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCX121XKIPOIDetector() + { + Destroy(); + } + + // + // Actions and Tools ... + + // #region Zone Detectors ... + int DetectSupports( + XBoxZone &zones[], + int barIndex, + int loopback = 50, + bool forceValidation = true, + int validationLength = 7, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + XClean(zones); + + // + // Normalize ... + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + + // + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + if (loopback < 2) + { + loopback = 2; + } + + // + if (validationLength < 2) + { + validationLength = 2; + } + + // + // Preparing Loops ... + XOHCL tmpBar; + bool has = false; + double upper = 0; + double lower = 0; + XBoxZone tmpZone; + string type = NULL; + double tmpValue = 0; + datetime from = NULL; + int start = barIndex; + int end = barIndex + loopback; + datetime to = GetBarTime(forSymbol, forPeriod, barIndex); + for (int i = start; i < end; i++) + { + // + // Initialize Bar ... + if (tmpBar.Init(forSymbol, forPeriod, i)) + { + // + // Check Has Shadow ... + has = tmpBar.GetHighShadow() > 0 || + tmpBar.GetLowShadow() > 0; + if (has) + { + // + // Check Support or Resistance ... + + // + // Support ... + tmpValue = tmpBar.FindLowest(validationLength, MODE_LOW); + has = NotEmptyZero(tmpValue) && + tmpValue == tmpBar.low; + + // + if (has) + { + // + tmpZone.Clean(); + lower = tmpValue; + from = tmpBar.time; + upper = tmpBar.GetDown(); + type = ToXString(X_BAR_PATTERN_SUPPORT); + has = tmpZone.Init( + forSymbol, + forPeriod, + upper, + lower, + from, + to, + X_DIRECTION_BULLISH, + type // + ); + if (has) + { + // + AddRef( + tmpZone, + zones // + ); + + // + tmpZone.Clean(); + } + } + } + + // + tmpBar.Clean(); + } + } + + // + // Validate ... + if (HasChild(zones) && forceValidation) + { + // + ValidateZones( + zones, + barIndex // + ); + } + + // + result = ArraySize(zones); + + // + return result; + } + + int DetectResistances( + XBoxZone &zones[], + int barIndex, + int loopback = 50, + bool forceValidation = true, + int validationLength = 7, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + XClean(zones); + + // + // Normalize ... + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + + // + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + if (loopback < 2) + { + loopback = 2; + } + + // + if (validationLength < 2) + { + validationLength = 2; + } + + // + // Preparing Loops ... + XOHCL tmpBar; + bool has = false; + double upper = 0; + double lower = 0; + XBoxZone tmpZone; + string type = NULL; + double tmpValue = 0; + datetime from = NULL; + int start = barIndex; + int end = barIndex + loopback; + datetime to = GetBarTime(forSymbol, forPeriod, barIndex); + for (int i = start; i < end; i++) + { + // + // Initialize Bar ... + if (tmpBar.Init(forSymbol, forPeriod, i)) + { + // + // Check Has Shadow ... + has = tmpBar.GetHighShadow() > 0 || + tmpBar.GetLowShadow() > 0; + if (has) + { + // + // Check Support or Resistance ... + + // + // Resistance ... + tmpValue = tmpBar.FindHighest(validationLength, MODE_HIGH); + has = NotEmptyZero(tmpValue) && + tmpValue == tmpBar.high; + if (has) + { + // + tmpZone.Clean(); + upper = tmpValue; + from = tmpBar.time; + lower = tmpBar.GetUp(); + type = ToXString(X_BAR_PATTERN_RESISTANCE); + has = tmpZone.Init( + forSymbol, + forPeriod, + upper, + lower, + from, + to, + X_DIRECTION_BEARISH, + type // + ); + if (has) + { + // + AddRef( + tmpZone, + zones // + ); + + // + tmpZone.Clean(); + } + } + } + + // + tmpBar.Clean(); + } + } + + // + // Validate ... + if (HasChild(zones) && forceValidation) + { + // + ValidateZones( + zones, + barIndex // + ); + } + + // + result = ArraySize(zones); + + // + return result; + } + + void ValidateZones( + XBoxZone &zones[], + int barIndex = 0, + ENUM_X_BOUNDARY_PRICE forPriceType = X_BOUNDARY_PRICE_UP_DOWN // + ) + { + // + bool has = false; + + // + // Validation ... + has = HasChild(zones) && + IsXValid(forPriceType); + if (!has) + { + return; + } + + // + // Normalizetion ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL tmpBar; + XBoxZone tmp; + XBoxZone tmps[]; + double tmpValue = 0; + for (int i = 0; i < ArraySize(zones); i++) + { + // + tmp = zones[i]; + + // + // Validate Zone ... + has = false; + for (int j = barIndex; j < tmp.FromIndex(); j++) + { + // + // Initial Bar ... + if (tmpBar.Init(tmp.symbol, tmp.period, j)) + { + // + tmpValue = forPriceType == X_BOUNDARY_PRICE_UP_DOWN + ? tmp.IsBullish() + ? tmpBar.GetDown() + : tmpBar.GetUp() + : forPriceType == X_BOUNDARY_PRICE_HIGH_LOW + ? tmp.IsBullish() + ? tmpBar.low + : tmpBar.high + : EMPTY_VALUE; + if (NotEmptyZero(tmpValue)) + { + // + // Check Break ... + has = tmp.IsBullish() + ? tmpValue < tmp.lower + : tmpValue > tmp.upper; + + // + // If Breakes ... + if (has) + { + break; + } + } + + // + tmpBar.Clean(); + } + } + + // + // Not Breaked ... + if (!has) + { + // + AddIfNotExists( + tmp, + tmps // + ); + } + + // + tmp.Clean(); + } + + // + // Update Zones ... + XClean(zones); + Copy( + tmps, + zones // + ); + XClean(tmps); + } + + void GetCurrentStructure( + XBoxZone &supports[], + XBoxZone &resistances[], + XBoxZone &minorSupport, + XBoxZone &majorSupport, + XBoxZone &minorResistance, + XBoxZone &majorResistance, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forMinorPeriod = NULL, + ENUM_TIMEFRAMES forMajorPeriod = NULL, + int loopback = 50, + int minorValidation = 7, + int majorValidation = 14 // + ) + { + // + bool has = false; + + // + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forMinorPeriod)) + { + forMinorPeriod = period; + } + if (!IsXValid(forMajorPeriod)) + { + forMajorPeriod = period; + } + + // + int tmpIDX = -1; + int supportsCount = 0; + XBoxZone tmpSupports[]; + int resistancesCount = 0; + XBoxZone tmpResistances[]; + + // + // Detect Minors ... + + // + supportsCount = DetectSupports( + tmpSupports, + barIndex, + loopback, + true, // Force Validation ... + minorValidation, + forSymbol, + forMinorPeriod // + ); + if (IsValidSize(supportsCount)) + { + // + FillNotExists( + supports, + tmpSupports // + ); + + // + tmpIDX = GetYoungest(tmpSupports); + if (IsValidIndex(tmpIDX)) + { + minorSupport = tmpSupports[tmpIDX]; + } + } + + // + resistancesCount = DetectResistances( + tmpResistances, + barIndex, + loopback, + true, // Force Validation ... + minorValidation, + forSymbol, + forMinorPeriod // + ); + if (IsValidSize(resistancesCount)) + { + // + FillNotExists( + resistances, + tmpResistances // + ); + + // + tmpIDX = GetYoungest(tmpResistances); + if (IsValidIndex(tmpIDX)) + { + minorResistance = tmpResistances[tmpIDX]; + } + } + + // + XClean(tmpSupports); + XClean(tmpResistances); + + // + // Detect Majors ... + + // + supportsCount = DetectSupports( + tmpSupports, + barIndex, + loopback, + true, // Force Validation ... + majorValidation, + forSymbol, + forMajorPeriod // + ); + if (IsValidSize(supportsCount)) + { + // + UpdateToTime(tmpSupports); + + // + FillNotExists( + supports, + tmpSupports // + ); + + // + tmpIDX = GetLowest(tmpSupports); + if (IsValidIndex(tmpIDX)) + { + majorSupport = tmpSupports[tmpIDX]; + } + } + + // + resistancesCount = DetectResistances( + tmpResistances, + barIndex, + loopback, + true, // Force Validation ... + majorValidation, + forSymbol, + forMajorPeriod // + ); + if (IsValidSize(resistancesCount)) + { + // + UpdateToTime(tmpResistances); + + // + FillNotExists( + resistances, + tmpResistances // + ); + + // + tmpIDX = GetHighest(tmpResistances); + if (IsValidIndex(tmpIDX)) + { + majorResistance = tmpResistances[tmpIDX]; + } + } + + // + XClean(tmpSupports); + XClean(tmpResistances); + } + + bool HasStructure( + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forMinorPeriod = NULL, + ENUM_TIMEFRAMES forMajorPeriod = NULL, + int loopback = 50, + int minorValidation = 7, + int majorValidation = 14 // + ) + { + // + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone minorSupport; + XBoxZone majorSupport; + XBoxZone minorResistance; + XBoxZone majorResistance; + + // + GetCurrentStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + barIndex, + forSymbol, + forMinorPeriod, + forMajorPeriod, + loopback, + minorValidation, + majorValidation // + ); + + // + bool result = + majorSupport.IsValid() && + majorResistance.IsValid(); + + // + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + return result; + } + + void RefineStructure( + XBoxZone &supports[], + XBoxZone &resistances[], + XBoxZone &minorSupport, + XBoxZone &majorSupport, + XBoxZone &minorResistance, + XBoxZone &majorResistance, + int loopback = 500, + double breakThreshold = 5, + ENUM_X_PRICE breakBy = X_PRICE_CLOSE // + ) + { + // + // Support ... + if (HasChild(supports)) + { + // + for (int i = 0; i < ArraySize(supports); i++) + { + // + RefineZone( + supports[i], + loopback, + breakThreshold, + breakBy // + ); + } + } + + // + // Resistance ... + if (HasChild(resistances)) + { + // + for (int i = 0; i < ArraySize(resistances); i++) + { + // + RefineZone( + resistances[i], + loopback, + breakThreshold, + breakBy // + ); + } + } + + // + RefineZone( + minorSupport, + loopback, + breakThreshold, + breakBy // + ); + + // + RefineZone( + majorSupport, + loopback, + breakThreshold, + breakBy // + ); + + // + RefineZone( + minorResistance, + loopback, + breakThreshold, + breakBy // + ); + + // + RefineZone( + majorResistance, + loopback, + breakThreshold, + breakBy // + ); + } + + void RefineZone( + XBoxZone &zone, + int loopback = 500, + double breakThreshold = 5, + ENUM_X_PRICE breakBy = X_PRICE_CLOSE // + ) + { + // + bool has = + zone.IsValid() && + IsXValid(breakBy); + if (!has) + { + return; + } + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + breakThreshold = NormalizeDouble(breakThreshold, 0, 50); + + // + XOHCL iBar; + int start = zone.FromIndex(); + int end = start + loopback; + double point = GetPoints(zone.symbol); + double breakDistance = point * breakThreshold; + for (int i = start; i < end; i++) + { + // + has = iBar.Init(zone.symbol, zone.period, i); + if (has) + { + // + // Check Rejections ... + has = zone.IsBullish() + ? iBar.low < zone.upper && + iBar.GetDown() > zone.upper + : iBar.high > zone.upper && + iBar.GetUp() < zone.upper; + if (has) + { + // + Add( + iBar.time, + zone.tests // + ); + } + + // + // Check Break ... + double bPrice = iBar.GetPrice(breakBy); + has = + zone.IsBullish() + ? bPrice < zone.lower - breakDistance + : bPrice > zone.upper + breakDistance; + if (has) + { + // + zone.breakAt = iBar.time; + break; + } + } + + // + iBar.Clean(); + } + + // + has = IsXValid(zone.breakAt); + if (has) + { + // + zone.at = zone.from; + zone.from = zone.breakAt; + } + } + + bool DetectRecentSwings( + XBoxZone &swingHigh, + XBoxZone &swingLow, + int barIndex = 0, + int swingsValidationLength = 50, + int loopback = 500, + ENUM_TIMEFRAMES forPeriod = NULL, + bool forceRefineZones = true // + ) + { + // + swingLow.Clean(); + swingHigh.Clean(); + + // + loopback = NormalizeInt(loopback, 5); + barIndex = kiParser.NormalizeBarIndex(barIndex); + swingsValidationLength = NormalizeInt(swingsValidationLength, 5); + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL iBar; + int iIDX = -1; + double low = 0; + double high = 0; + int lowIDX = -1; + int highIDX = -1; + bool has = false; + double iValue = 0; + datetime lowAt = NULL; + datetime highAt = NULL; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, forPeriod, i); + if (!has) + { + continue; + } + + // + iIDX = iBar.FindLowestIndex(swingsValidationLength, MODE_LOW); + has = IsValidIndex(iIDX); + if (has) + { + // + iValue = iLow(iBar.symbol, iBar.period, iIDX); + + // + // Check Can Set Low ... + has = (!NotEmptyZero(low) || + (NotEmptyZero(low) && iValue < low)) && + IsValidSwing( + iValue, + iIDX, + barIndex, + iBar.symbol, + iBar.period, + X_SWING_LOW // + ); + if (has) + { + // + low = iValue; + lowIDX = iIDX; + lowAt = iBar.time; + } + } + + // + iIDX = iBar.FindHighestIndex(swingsValidationLength, MODE_HIGH); + has = IsValidIndex(iIDX); + if (has) + { + // + iValue = iHigh(iBar.symbol, iBar.period, iIDX); + + // + // Check Can Set High ... + has = (!NotEmptyZero(high) || + (NotEmptyZero(high) && iValue > high)) && + IsValidSwing( + iValue, + iIDX, + barIndex, + iBar.symbol, + iBar.period, + X_SWING_HIGH // + ); + if (has) + { + // + high = iValue; + highIDX = iIDX; + highAt = iBar.time; + } + } + + // + iBar.Clean(); + } + + // + // Recent Low Swing ... + has = + IsXValid(lowAt) && + NotEmptyZero(low) && + IsValidIndex(lowIDX); + if (has) + { + // + has = iBar.Init(symbol, forPeriod, lowIDX); + has = has && + swingLow.Init( + iBar.symbol, + iBar.period, + iBar.GetDown(), + low, + GetBarTime(iBar.symbol, iBar.period, lowIDX + swingsValidationLength - 1), + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BULLISH, + ToXString(X_BAR_PATTERN_LOW), + lowAt // + ); + if (has && forceRefineZones) + { + RefineZone(swingLow, 500, 5, X_PRICE_CLOSE); + } + } + + // + // Recent High Swing ... + has = + IsXValid(highAt) && + NotEmptyZero(high) && + IsValidIndex(highIDX); + if (has) + { + // + has = iBar.Init(symbol, forPeriod, highIDX); + has = has && + swingHigh.Init( + iBar.symbol, + iBar.period, + high, + iBar.GetUp(), + GetBarTime(iBar.symbol, iBar.period, lowIDX + swingsValidationLength - 1), + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BEARISH, + ToXString(X_BAR_PATTERN_HIGH), + highAt // + ); + if (has && forceRefineZones) + { + RefineZone(swingHigh, 500, 5, X_PRICE_CLOSE); + } + } + + // + bool result = swingLow.IsValid() && + swingHigh.IsValid(); + + // + return result; + } + + bool HasOrderFlow( + XBoxZone &flow[], + int barIndex = 0, + int flowValidationLength = 5, + ENUM_X_DIRECTION flowDir = X_DIRECTION_NONE, + int loopback = 50, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + bool result = false; + + // + XClean(flow); + + // + // Validate ... + result = + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Normalizing Data ... + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + loopback = NormalizeInt(loopback, 5); + barIndex = kiParser.NormalizeBarIndex(barIndex); + flowValidationLength = NormalizeInt(flowValidationLength, 2); + + // + // Handle Works ... + + // + XOHCL iBar; + int iIndex = -1; + bool has = false; + XBoxZone tmpZone; + double iPrice = 0; + ENUM_X_PRICE iPriceType; + bool isBullish = !HasDirection(flowDir) || IsXBullish(flowDir); + bool isBearish = !HasDirection(flowDir) || IsXBearish(flowDir); + + // + // Looping Reversal ... + int start = barIndex + loopback; + int end = barIndex; + for (int i = start; i > end; i--) + { + // + has = iBar.Init(forSymbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Check iBar is Low Swing ... + if (isBullish) + { + // + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + iPrice = iBar.GetPrice(iPriceType); + has = iPrice == iBar.FindLowest(iIndex, flowValidationLength, iPriceType); + has = has && + IsValidSwing( + iPrice, + iBar.Index(), + barIndex, + iBar.symbol, + iBar.period, + X_SWING_LOW // + ); + if (has) + { + // + // Flow Detected ... + tmpZone.Clean(); + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_DOWN + : X_PRICE_UP; + has = tmpZone.Init( + iBar.symbol, + iBar.period, + iBar.GetPrice(iPriceType), + iPrice, + iBar.time, + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BULLISH, + ToXString(X_BAR_PATTERN_LOW) // + ); + if (has) + { + // + AddIfNotExists( + tmpZone, + flow // + ); + + // + tmpZone.Clean(); + } + } + } + + // + // Check iBar is High Swing ... + if (isBearish) + { + // + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + iPrice = iBar.GetPrice(iPriceType); + has = iPrice == iBar.FindHighest(iIndex, flowValidationLength, iPriceType); + has = has && + IsValidSwing( + iPrice, + iBar.Index(), + barIndex, + iBar.symbol, + iBar.period, + X_SWING_HIGH // + ); + if (has) + { + // + // Flow Detected ... + tmpZone.Clean(); + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_UP + : X_PRICE_DOWN; + has = tmpZone.Init( + iBar.symbol, + iBar.period, + iPrice, + iBar.GetPrice(iPriceType), + iBar.time, + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BEARISH, + ToXString(X_BAR_PATTERN_HIGH) // + ); + if (has) + { + // + AddIfNotExists( + tmpZone, + flow // + ); + + // + tmpZone.Clean(); + } + } + } + + // + iBar.Clean(); + tmpZone.Clean(); + } + + // + result = HasChild(flow); + if (result) + { + Sort(flow); + } + + // + return result; + } + + bool IsValidSwing( + double price, + int swingIDX, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_SWING_TYPE swingType = X_SWING_NONE // + ) + { + // + bool result = false; + + // + result = + NotEmptyZero(price) && + IsXValid(swingType) && + IsValidIndex(swingIDX) && + swingIDX >= barIndex; + if (!result) + { + return result; + } + + // + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL iBar; + bool has = false; + for (int i = barIndex; i <= (swingIDX - barIndex); i++) + { + // + has = iBar.Init(forSymbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Check Price Break ... + has = + (swingType == X_SWING_LOW && + iBar.low < price) || + (swingType == X_SWING_HIGH && + iBar.high > price); + if (has) + { + break; + } + + // + iBar.Clean(); + } + + // + result = !has && !iBar.IsValid(); + + // + iBar.Clean(); + + // + return result; + } + // #endregion + + // #region Hasers ... + bool HasVolatilitySwitchedHigh( + int barIndex = 0, + int loopback = 3 // + ) + { + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + loopback = NormalizeInt(loopback, 1); + + // + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + result = kiParser.IsVolatilitySwitchdToHigh(i); + if (result) + { + break; + } + } + + // + return result; + } + // #endregion + + // #region Bar Patterns ... + void FillStrategy1Patterns( + ENUM_X_BAR_PATTERN &patterns[], + ENUM_X_DIRECTION &dirs[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + XClean(dirs); + XClean(patterns); + + // + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + GetAllBarPatters(patterns, dirs); + + // + // Add(X_BAR_PATTERN_FVG, patterns); + // Add(forDir, dirs); + } + + void RefactorStrategy1OperationalZone(XBoxZone &zone) + { + + // + if (!zone.IsValid()) + { + return; + } + + // + // Refine Zone ... + RefineZone(zone); + + // + // SL Refactoring ... + + // + XOHCL toBar; + if (zone.ToBar(toBar)) + { + // + int to = zone.ToIndex(); + int from = zone.FromIndex(); + int length = from - to; + double iValue = + zone.IsBullish() + ? toBar.FindLowest(length, MODE_LOW) + : zone.IsBearish() + ? toBar.FindHighest(length, MODE_HIGH) + : EMPTY_VALUE; + if (NotEmptyZero(iValue)) + { + // + if (zone.IsBullish()) + { + zone.lower = MathMin(zone.lower, iValue); + } + + // + if (zone.IsBearish()) + { + zone.upper = MathMax(zone.upper, iValue); + } + } + } + toBar.Clean(); + } + + /* + * Check Recently Pattern Zone is Rejected or not ... + * + * @param zone: XBoxZone, Touched Zone ... + * @param patterns: ENUM_X_BAR_PATTERN, Allowed to Check Patterns ... + * @param patternsDir: ENUM_X_DIRECTION, Allowed Directions ... + * @param price: double, a Price to Check Toch or Reject ... + * @param barIndex: int, Bar Index to Start Checking ... + * @param loopback: int, Loopback for Pattern Formations ... + * @param forPeriod: ENUM_TIMEFRAMES, Time Frame to Check Patterns ... + * @param forDir: ENUM_X_DIRECTION, Directions for Pattern's Formation Check ... + * + * @return ( bool ) + */ + bool HasRecentPatternRejected( + XBoxZone &zone, + ENUM_X_BAR_PATTERN &patterns[], + ENUM_X_DIRECTION &patternsDir[], + int barIndex = 0, + int loopback = 5, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + // Validate ... + result = + HasChild(patterns) && + HasChild(patternsDir) && + ArraySize(patterns) == ArraySize(patternsDir); + if (!result) + { + return result; + } + + // + // Normalize ... + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL bar; + result = bar.Init(symbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int iBullishIDX = -1; + int iBearishIDX = -1; + bool isBullish = false; + bool isBearish = false; + XBoxZone iBullishZones[]; + XBoxZone iBearishZones[]; + XPatternAnalysis iAnalysis; + XPatternAnalysisConfig iConfig; + + // + // Preparing Pattern Analysis Config ... + iConfig.Default(); + + // + Copy( + patterns, + iConfig.allowedPatterns // + ); + Copy( + patternsDir, + iConfig.allowedDirs // + ); + + // + // Looping Back ... + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Initialize Bar ... + has = iBar.Init(symbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Analyse Patterns ... + has = AnalyseBarPatterns(iBar, iAnalysis, iConfig); + if (!has) + { + // + iBar.Clean(); + continue; + } + + // + // Bullish ... + has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH); + isBullish = + HasChild(iBullishZones) && + HasRejected(iBullishIDX, bar, iBullishZones); + } + + // + // Bearish ... + has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH); + isBearish = + HasChild(iBearishZones) && + HasRejected(iBearishIDX, bar, iBearishZones); + } + + // + // Summarizing Result ... + has = + HasDirection(forDir) + ? (isBullish && !isBearish && IsXBullish(forDir)) || + (isBearish && !isBullish && IsXBearish(forDir)) + : (isBullish && !isBearish) || (isBearish && !isBullish); + if (has) + { + // + // Fill Zones ... + if (isBullish) + { + zone = iBullishZones[iBullishIDX]; + } + else + { + zone = iBearishZones[iBearishIDX]; + } + break; + } + + // + // Cleanup Resource ... + iBar.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + } + + // + // Cleanup Resources ... + bar.Clean(); + iBar.Clean(); + iConfig.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + + // + result = zone.IsValid(); + + // + return result; + } + // #endregion + + // #region Switches ... + int HasKIFastSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsKIFastSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_FAST), + GetBarTime(symbol, period, i), + kiHelper.GetKIFast(i), + kiHelper.GetKIFast(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsKIFastSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_FAST), + GetBarTime(symbol, period, i), + kiHelper.GetKIFast(i), + kiHelper.GetKIFast(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasKISlowSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsKISlowSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetKISlow(i), + kiHelper.GetKISlow(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsKISlowSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetKIFast(i), + kiHelper.GetKIFast(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasKISuperSlowSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsKISuperSlowSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_SUPER_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetKISuperSlow(i), + kiHelper.GetKISuperSlow(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsKISuperSlowSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_SUPER_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetKIFast(i), + kiHelper.GetKIFast(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasKIWaveSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsKIWaveSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_WAVE), + GetBarTime(symbol, period, i), + kiHelper.GetKIWave(i), + kiHelper.GetKIWave(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsKIWaveSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_WAVE), + GetBarTime(symbol, period, i), + kiHelper.GetKIWave(i), + kiHelper.GetKIWave(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasMAFastSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsMAFastSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_FAST), + GetBarTime(symbol, period, i), + kiHelper.GetMAFast(i), + kiHelper.GetMAFast(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsMAFastSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_FAST), + GetBarTime(symbol, period, i), + kiHelper.GetMAFast(i), + kiHelper.GetMAFast(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasMASlowSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsMASlowSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetMASlow(i), + kiHelper.GetMASlow(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsMASlowSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetMAFast(i), + kiHelper.GetMAFast(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasMASuperSlowSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsMASuperSlowSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_SUPER_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetMASuperSlow(i), + kiHelper.GetMASuperSlow(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsMASuperSlowSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_SUPER_SLOW), + GetBarTime(symbol, period, i), + kiHelper.GetMAFast(i), + kiHelper.GetMAFast(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasMACrossedSwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsMACrossoverSwitchedToBullish(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_CROSS), + GetBarTime(symbol, period, i), + MathMin(kiHelper.GetMAFast(i), kiHelper.GetMASlow(i)), + MathMin(kiHelper.GetMAFast(i + 1), kiHelper.GetMASlow(i + 1)), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsMACrossoverSwitchedToBearish(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_MA_CROSS), + GetBarTime(symbol, period, i), + MathMin(kiHelper.GetMAFast(i), kiHelper.GetMASlow(i)), + MathMin(kiHelper.GetMAFast(i + 1), kiHelper.GetMASlow(i + 1)), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + + int HasATRVolatilitySwitch( + XDirectionShift &switches[], + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + XClean(switches); + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool has = false; + XDirectionShift iShift; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Bullish ... + bool hasBullish = kiParser.IsVolatilitySwitchdToHigh(i); + has = hasBullish && isBullish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_ATR), + GetBarTime(symbol, period, i), + kiHelper.GetATR(i), + kiHelper.GetATR(i + 1), + symbol, + period, + X_DIRECTION_BULLISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + + // + // Bearish ... + bool hasBearish = kiParser.IsVolatilitySwitchdToLow(i); + has = hasBearish && isBearish; + if (has) + { + // + iShift.Clean(); + has = iShift.Init( + ToXString(X121_XKI_ATR), + GetBarTime(symbol, period, i), + kiHelper.GetATR(i), + kiHelper.GetATR(i + 1), + symbol, + period, + X_DIRECTION_BEARISH // + ); + if (has) + { + // + AddIfNotExists( + iShift, + switches // + ); + + // + iShift.Clean(); + } + } + } + + // + result = ArraySize(switches); + + // + return result; + } + // #endregion + + // #region Peak and Vale ... + // TODO: Implement Root of Changes when IsPeakOverLast or IsValeUnderLast Happens ... + // #endregion + + // #region Rejecteds ... + bool IsKIFastRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetKIFast(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsKISlowRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetKISlow(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsKISuperSlowRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetKISuperSlow(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsKIUpperRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetKIUpper(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsKILowerRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetKILower(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsMAFastRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetMAFast(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsMASlowRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetMASlow(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsMASuperSlowRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetMASuperSlow(barIndex); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsPrevPeakRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetPeak(barIndex + 1); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsPrevValeRejected( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL bar; + result = + kiParser.IsValid() && + bar.Init(forSymbol, forPeriod, barIndex); + if (!result) + { + return result; + } + + // + double iValue = kiHelper.GetVale(barIndex + 1); + + // + bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false); + bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false); + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + bar.Clean(); + + // + return result; + } + // #endregion + + // #region Counters ... + int CountKIFastRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsKIFastRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountKISlowRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsKISlowRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountKISuperSlowRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsKISuperSlowRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountKIUpperRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsKIUpperRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountKILowerRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsKILowerRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountMAFastRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsMAFastRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountMASlowRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsMASlowRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountMASuperSlowRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsMASuperSlowRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountPrevPeakRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsPrevPeakRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + + int CountPrevValeRejects( + int barIndex = 0, + int loopback = 10, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + bool isBullish = !HasDirection(forDir) || IsXBullish(forDir); + bool isBearish = !HasDirection(forDir) || IsXBearish(forDir); + + // + bool is = false; + bool hasBullish = false; + bool hasBearish = false; + ENUM_X_DIRECTION tmpDir; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + is = IsPrevValeRejected( + tmpDir, + i, + forSymbol, + forPeriod // + ); + hasBullish = is && IsXBullish(tmpDir); + hasBearish = is && IsXBearish(tmpDir); + + // + if ((isBullish && hasBullish) || + (isBearish && hasBearish)) + { + result++; + } + } + + // + return result; + } + // #endregion + + // + // Others ... + + /** + * Destroy ... + */ + void Destroy() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + + // + ZeroMemory(kiHelper); + ZeroMemory(kiParser); + } + + // + // Testers ... + + // + // Protected ... + protected: + // + // Props ... + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..6bde21b --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 @@ -0,0 +1,707 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121XKIPoiDrawer ... +// Description: X121XKI 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 X121XKI POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" + +// +// Implementation ... +class XCX121XKIPOIDrawer : public XCPOIDrawer +{ + // + public: + // + // Props ... + + // + // Tested Zones ... + color testedBullishColor; + color testedBearishColor; + + // + // Breaked Zones ... + color breakedBullishColor; + color breakedBearishColor; + + // + // FakeBreaked Zones ... + color fakeBreakedBullishColor; + color fakeBreakedBearishColor; + + // + // Constructor ... + XCX121XKIPOIDrawer() : XCPOIDrawer() + { + Default(); + } + + // + // Deconstructor ... + ~XCX121XKIPOIDrawer() + { + } + + // + // Overrides ... + + /** + * Do additional Configurations for Child Classes ... + */ + void virtual Default() override + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrAqua; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrMagenta; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + + // + testedBullishColor = clrLime; + breakedBullishColor = clrGreen; + fakeBreakedBullishColor = clrYellow; + + // + testedBearishColor = clrRed; + breakedBearishColor = clrDarkRed; + fakeBreakedBearishColor = clrDarkOrange; + } + + // + // Get Specified Directional Arrow Anchor ... + ENUM_ARROW_ANCHOR GetArrowAnchor(ENUM_X_DIRECTION forDir) + { + // + ENUM_ARROW_ANCHOR result = ANCHOR_BOTTOM; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + int GetArrowCode(ENUM_X_DIRECTION forDir) + { + // + int result = 159; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? 233 + : 234; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + color GetArrowColor(ENUM_X_DIRECTION forDir) + { + // + color result = clrYellow; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? clrAqua + : clrMagenta; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Price Type ... + ENUM_X_PRICE GetArrowPriceType(ENUM_X_DIRECTION forDir) + { + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? X_PRICE_LOW + : X_PRICE_HIGH; + } + + // + return result; + } + + /** + * Get Tested Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetTestedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? testedBullishColor + : testedBearishColor; + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetPatternStyle( + style, + zone.dir // + ); + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param forDir: Specified Direction ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + forDir // + ); + + // + style.width = 2; + style.style = STYLE_DASH; + + // + return result; + } + + /** + * Get Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? breakedBullishColor + : breakedBearishColor; + + // + return result; + } + + /** + * Get Fake Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetFakeBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? fakeBreakedBullishColor + : fakeBreakedBearishColor; + + // + return result; + } + + /** + * Fill Arrow Based Drawing Specs ... + * + * @param forDir: Specified Direction ... + * @param arrowPriceType: ENUM_X_PRICE, refrence for Arrow Price ... + * @param arrowCode: int, reference for Arrow Code ... + * @param arrowWidth: int, reference for Arrow Width ... + * @param arrowColor: color, reference for Arrow Color ... + * @param arrowAnchor: ENUM_ARROW_ANCHOR, reference for Arrow Anchor ... + */ + void FillArrowSpecs( + ENUM_X_DIRECTION forDir, + ENUM_X_PRICE &arrowPriceType, + int &arrowCode, + int &arrowWidth, + color &arrowColor, + ENUM_ARROW_ANCHOR &arrowAnchor // + ) + { + // + // Prepare ... + arrowCode = 159; + arrowWidth = 2; + arrowColor = CLR_NONE; + arrowAnchor = ANCHOR_BOTTOM; + arrowPriceType = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + arrowCode = GetArrowCode(forDir); + arrowColor = GetArrowColor(forDir); + arrowAnchor = GetArrowAnchor(forDir); + arrowPriceType = GetArrowPriceType(forDir); + } + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyTestedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetTestedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Breaked Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyBreakedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyFakeBreakStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetFakeBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Pattern Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPatternStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetPatternStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPatternsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBoxObject *iBoxObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iBoxObj = (XCBoxObject *)objects.At(i); + iName = iBoxObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + /** + * Apply Style to Specified Pivot Object ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPivotStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPivotsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBarArrowObject *iObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iObj = (XCBarArrowObject *)objects.At(i); + iName = iObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyPivotStyle( + iObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iObj); + } + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/X121XKIEA/Documents/Analysation.md b/BKPS/14041018/X121XKIEA/Documents/Analysation.md new file mode 100644 index 0000000..503a462 --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Documents/Analysation.md @@ -0,0 +1,201 @@ +📄 X121XKIEA Framework Pricing & Skill Assessment Document + +Overview + +This document synthesizes the group discussion around the analysis of the X121XKIEA MQL5 Expert Advisor framework, the evaluation of programming skills demonstrated in its design, and the pricing strategy options for monetizing the framework. + +1. Framework Analysis + +High-Level Architecture + +Core Utilities: XCBase, XCommonLib, XModelsLib, XOHCL (bar abstraction). + +Market Structure & Patterns: XCBarAnalyser, XCMarketPatternDetector. + +Visualization: XPOI, XCPOIDrawer, chart object libraries. + +Trading & Risk Management: XCAccount, XCTrade, XCVolume, XCTarget, XCGuard. + +Signalling & Execution: XCBaseSignaller, XCTradeManager. + +Indicators: XKI (Ichimoku/KI composite), XCT (candle timer), XCC (chart cosmetics). + +EA Scaffolding: XCBaseExpert, XCBackTesterEA, X121XKIEABackTester. + +Ancillary: XCAlert, XCDataCollector, XCHttp, XCMD5. + +Strengths + +Modular, layered design. + +Advanced risk management (multi-target, risk-free, guards). + +Rich visualization overlays. + +Event-driven orchestration. + +Issues Identified + +Constructors incorrectly declared with void. + +Unsafe use of ZeroMemory(this) in structs. + +Incomplete/truncated implementations. + +Guard/target concurrency risks. + +Config parsing robustness. + +Recommendations + +Correct constructor/destructor syntax. + +Replace unsafe memory reset patterns. + +Complete truncated modules. + +Add unit-style validations. + +Improve config parsing (JSON-like). + +2. Programming Skill Assessment + +Skill Profile Matrix (Qualitative) + +Architecture: Advanced modular design, clear separation of concerns. + +Syntax & Language: Strong struct/class usage, consistent naming; needs syntactic polish. + +Trading Logic: Sophisticated risk and signal management. + +Visualization: Rich overlays, QA-friendly. + +Maintainability: Event-driven, alerts, config parsing; needs more robust validation. + +Innovation: Pivot regression, multi-strategy signaller design. + +Quantified Scores (1–10) + +Architecture: 9.5 + +Syntax & Language: 7.5 + +Trading Logic: 9.0 + +Visualization: 8.5 + +Maintainability: 8.0 + +Innovation: 9.0 + +Overall Rating: 8.7 / 10 (Advanced/Expert tier) + +3. Pricing Analysis + +Methods Considered + +Cost-Based: $12,000–$15,000 (based on hours × rate). + +Value-Based: $10,000–$50,000 (based on trading edge and impact). + +Market-Based: $1,500–$3,000 (retail EA market), $8,000–$15,000 (institutional/private sale). + +Comparison Table + +Method + +Price Range + +Best Use Case + +Cost-Based + +$12,000–$15,000 + +Consulting, custom builds + +Value-Based + +$10,000–$50,000 + +Exclusive licensing, institutions + +Market-Based + +$1,500–$3,000 (retail)
$8,000–$15,000 (institutional) + +Retail vs private sale + +4. Pricing Strategy Plan + +Retail Market (MQL5 Market) + +Target: Individual traders. + +Price: $1,500–$3,000. + +Pros: Large audience, visibility. + +Cons: Lower margins, copycat risk. + +Best Use: Lite version. + +Institutional Clients + +Target: Prop firms, hedge funds. + +Price: $8,000–$15,000. + +Pros: High margins, prestige. + +Cons: Requires performance proof. + +Best Use: Full framework. + +Licensing Model + +Target: Firms needing ongoing access. + +Price: $2,000–$5,000/year or $500–$1,000/month. + +Pros: Recurring revenue. + +Cons: Requires license enforcement. + +Best Use: Subscription with updates/support. + +Consulting + Custom Builds + +Target: Traders needing tailored solutions. + +Price: $12,000–$15,000/project. + +Pros: Direct monetization of expertise. + +Cons: Time-intensive. + +Best Use: Bespoke strategy builds. + +5. Recommended Strategy + +Dual Approach: + +Retail Lite version (~$2,000). + +Full institutional version (~$10,000–$15,000). + +Add Licensing: For recurring revenue and support. + +Consulting: Premium option for custom builds. + +Future Considerations + +Develop tiered pricing packages (Lite, Pro, Enterprise). + +Provide performance metrics (backtests, live results) to strengthen institutional sales. + +Expand strategy diversity (breakout, continuation, exhaustion signallers). + +End of Document + +https://copilot.microsoft.com/shares/pages/ERAAHojiAwN8eTuiKtiZ2 \ No newline at end of file diff --git a/BKPS/14041018/X121XKIEA/Documents/Analytics.pdf b/BKPS/14041018/X121XKIEA/Documents/Analytics.pdf new file mode 100644 index 0000000..f7909c7 Binary files /dev/null and b/BKPS/14041018/X121XKIEA/Documents/Analytics.pdf differ diff --git a/BKPS/14041018/X121XKIEA/Libraries/.gitkeep b/BKPS/14041018/X121XKIEA/Libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/BKPS/14041018/X121XKIEA/Libraries/x-saherelm.x121.xki.lib.mq5 b/BKPS/14041018/X121XKIEA/Libraries/x-saherelm.x121.xki.lib.mq5 new file mode 100644 index 0000000..afb85cf --- /dev/null +++ b/BKPS/14041018/X121XKIEA/Libraries/x-saherelm.x121.xki.lib.mq5 @@ -0,0 +1,124 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCX121XKIEALib ... +// Description: X121XKI Library ... +// +// +// 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 X121XKIEA Library" +#property strict + +// +// Imports ... +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// Enums ... + +// #region XKIStrategies ... +enum X121XKIStrategies +{ + X121_XKI_STRATEGY_UNKNOWN = 0, + X121_XKI_STRATEGY_1 = 1, + X121_XKI_STRATEGY_2 = 2, + X121_XKI_STRATEGY_3 = 3, + X121_XKI_STRATEGY_4 = 4, + X121_XKI_STRATEGY_5 = 5, + X121_XKI_STRATEGY_6 = 6, +}; +bool IsXValid(X121XKIStrategies value) +{ + return value != X121_XKI_STRATEGY_UNKNOWN; +} +string ToXString(X121XKIStrategies value) +{ + // + string result = NULL; + + // + if (IsXValid(value)) + { + // + switch (value) + { + // + case X121_XKI_STRATEGY_1: + result = "1"; + break; + // + case X121_XKI_STRATEGY_2: + result = "2"; + break; + // + case X121_XKI_STRATEGY_3: + result = "3"; + break; + // + case X121_XKI_STRATEGY_4: + result = "4"; + break; + // + case X121_XKI_STRATEGY_5: + result = "5"; + break; + // + case X121_XKI_STRATEGY_6: + result = "6"; + break; + } + } + + // + return result; +} +X121XKIStrategies ToX121XKIStrategy(string value) +{ + // + X121XKIStrategies result = X121_XKI_STRATEGY_UNKNOWN; + + // + if (IsXValid(value)) + { + // + if (value == ToXString(X121_XKI_STRATEGY_1)) + { + result = X121_XKI_STRATEGY_1; + } + else if (value == ToXString(X121_XKI_STRATEGY_2)) + { + result = X121_XKI_STRATEGY_2; + } + else if (value == ToXString(X121_XKI_STRATEGY_3)) + { + result = X121_XKI_STRATEGY_3; + } + else if (value == ToXString(X121_XKI_STRATEGY_4)) + { + result = X121_XKI_STRATEGY_4; + } + else if (value == ToXString(X121_XKI_STRATEGY_5)) + { + result = X121_XKI_STRATEGY_5; + } + else if (value == ToXString(X121_XKI_STRATEGY_6)) + { + result = X121_XKI_STRATEGY_6; + } + } + + // + return result; +} +// #endregion \ No newline at end of file diff --git a/BKPS/14041018/XCATBEA/Classes/xcatbea.expert.class.mq5 b/BKPS/14041018/XCATBEA/Classes/xcatbea.expert.class.mq5 new file mode 100644 index 0000000..53cb5a6 --- /dev/null +++ b/BKPS/14041018/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 == "DowJones30") + { + // + // 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/14041018/XCATBEA/Classes/xcatbea.signaller.class.mq5 b/BKPS/14041018/XCATBEA/Classes/xcatbea.signaller.class.mq5 new file mode 100644 index 0000000..1ba538b --- /dev/null +++ b/BKPS/14041018/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 = ToXSignal( + 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 = ToXSignal( + 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 = ToXSignal( + mConditions.triggerBlock.trigger, + mConditions.triggerBlock.signal, + targets, + slAdditional // + ); + XSignal insideTBSignal; + result = + result && + ToXSignal( + 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/14041018/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 b/BKPS/14041018/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 new file mode 100644 index 0000000..0692390 --- /dev/null +++ b/BKPS/14041018/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/14041018/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 b/BKPS/14041018/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..29c27aa --- /dev/null +++ b/BKPS/14041018/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/14041018/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 b/BKPS/14041018/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 new file mode 100644 index 0000000..0d093f1 --- /dev/null +++ b/BKPS/14041018/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/14041018/XCATBEA/Libraries/xcatbea.lib.mq5 b/BKPS/14041018/XCATBEA/Libraries/xcatbea.lib.mq5 new file mode 100644 index 0000000..c3c1442 --- /dev/null +++ b/BKPS/14041018/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.DrawBarArrow( + _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/14041018/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 b/BKPS/14041018/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 new file mode 100644 index 0000000..ebda6e9 --- /dev/null +++ b/BKPS/14041018/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/14041018/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 b/BKPS/14041018/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..9e828f0 --- /dev/null +++ b/BKPS/14041018/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/14041018/XFIMAEA/Classes/x-saherelm.xfima.expert.class.mq5 b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.expert.class.mq5 new file mode 100644 index 0000000..c23be68 --- /dev/null +++ b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.expert.class.mq5 @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAExpret ... +// Description: XFIMA 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 XFIMA Expert Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-expert.class.mq5" +#include "../Classes/x-saherelm.xfima.signaller.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCXFIMAExpret : public XCBaseExpert +{ + // + // Public ... + public: + // + + // + // Overrides ... + + /** + * Prepare Signallers per Symbol Config ... + * + * @param symbolConfig: XSymbolTradeConfig, Symbol Trade Configurations ... + */ + void PrepareSignallers(XSymbolTradeConfig &symbolConfig) override + { + // + // Validate ... + if (!symbolConfig.IsValid()) + { + return; + } + + // + // Instantiate Signaller ... + + // + // XFIMA Inputs ... + + // + XFIMAInputs fimaInputs; + fimaInputs.Default(); + fimaInputs.Hide(); + + // + // Instantiate Signaller Class ... + XCXFIMAStrategy1Signaller *fima1Signaller = new XCXFIMAStrategy1Signaller( + symbolConfig.symbol, + symbolConfig.period, + fimaInputs, + false // Process All Ticks ... + ); + if (!fima1Signaller.IsValid()) + { + // + fima1Signaller.Destroy(); + delete fima1Signaller; + ZeroMemory(fima1Signaller); + return; + } + + // + // Register Signaller ... + RegisterSignaller((XCBaseSignaller *)fima1Signaller); + + // + // Cleanup Resources ... + fimaInputs.Clean(); + ZeroMemory(fima1Signaller); + } + + /** + * Additional On Tick Processing if Required ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void virtual HandleOnTickAdditional(int barIndex = 0) + { + // + // Implement this if required ... + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 new file mode 100644 index 0000000..abf7177 --- /dev/null +++ b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 @@ -0,0 +1,10127 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Parser Class Library +// ---------------------------------------------------- +// Name: XCXFIMAHelperParser +// Description: provides all Indicator +// Helper Parse requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.xfima.helper.mq5" + +// +// Definitions ... + +// +// Implementation ... + +class XCXFIMAHelperParser : XCBase +{ + // + // Public ... + public: + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XCXFIMAHelperParser(XCXFIMAHelper *_helper) + { + // + helper = _helper; + symbol = _helper.GetSymbol(); + period = _helper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCXFIMAHelperParser() + { + ZeroMemory(helper); + } + + // + // Tools ... + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = helper != NULL && + helper.IsValid() && + IsXValid(symbol) && + IsXValid(period); + + // + return result; + } + + /** + * Normalize Bar Index ... + * + * @param barIndex: int, Provided Bar Index ... + * + * @return ( int ) + */ + int NormalizeBarIndex(int barIndex = 0) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = helper.NormalizeBarIndex(barIndex); + + // + return result; + } + + // + // Parsers ... + + // + // XSAR ... + + /** + * Check SAR is Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetSARState(barIndex); + result = state >= 1; + + // + return result; + } + + /** + * Check SAR is Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetSARState(barIndex); + result = state <= -1; + + // + return result; + } + + /** + * Check SAR is Switched to Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBullish = IsSARBullish(barIndex); + bool isPBullish = IsSARBullish(pBarIndex); + + // + result = isBullish && + !isPBullish; + + // + return result; + } + + /** + * Check SAR is Switched to Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBearish = IsSARBearish(barIndex); + bool isPBearish = IsSARBearish(pBarIndex); + + // + result = isBearish && + !isPBearish; + + // + return result; + } + + /** + * Count Bullish SAR(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishSARs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSARBullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish SAR(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishSARs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSARBearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + // + // XMA ... + + /** + * Check Fast Ma is Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetMAFastState(barIndex); + + // + result = state >= 1; + + // + return result; + } + + /** + * Check Slow Ma is Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetMASlowState(barIndex); + + // + result = state >= 1; + + // + return result; + } + + /** + * Check Fast Ma is Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetMAFastState(barIndex); + + // + result = state <= -1; + + // + return result; + } + + /** + * Check Slow Ma is Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetMASlowState(barIndex); + + // + result = state <= -1; + + // + return result; + } + + /** + * Check Fast Ma is Switched to Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMAFastBullish(barIndex); + bool isP = IsMAFastBullish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Slow Ma is Switched to Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMASlowBullish(barIndex); + bool isP = IsMASlowBullish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Fast Ma is Switched to Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMAFastBearish(barIndex); + bool isP = IsMAFastBearish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Slow Ma is Switched to Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMASlowBearish(barIndex); + bool isP = IsMASlowBearish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Fast Ma Over Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastOverSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double iSlow = helper.GetMASlow(barIndex); + + // + result = iFast > iSlow; + + // + return result; + } + + /** + * Check Fast Ma Under Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastUnderSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double iSlow = helper.GetMASlow(barIndex); + + // + result = iFast < iSlow; + + // + return result; + } + + /** + * Check Fast Ma Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double pFast = helper.GetMAFast(barIndex + 1); + + // + result = iFast > pFast; + + // + return result; + } + + /** + * Check Slow Ma Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iSlow = helper.GetMASlow(barIndex); + double pSlow = helper.GetMASlow(barIndex + 1); + + // + result = iSlow > pSlow; + + // + return result; + } + + /** + * Check Fast Ma Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double pFast = helper.GetMAFast(barIndex + 1); + + // + result = iFast < pFast; + + // + return result; + } + + /** + * Check Slow Ma Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iSlow = helper.GetMASlow(barIndex); + double pSlow = helper.GetMASlow(barIndex + 1); + + // + result = iSlow < pSlow; + + // + return result; + } + + /** + * Check MA Fast is Crossed Over Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedOverSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastOverSlow = IsMAFastOverSlow(barIndex); + bool isPFastOverSlow = IsMAFastOverSlow(barIndex + 1); + + // + result = isFastOverSlow && + !isPFastOverSlow; + + // + return result; + } + + /** + * Check MA Fast is Crossed Under Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedUnderSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastUnderSlow = IsMAFastUnderSlow(barIndex); + bool isPFastUnderSlow = IsMAFastUnderSlow(barIndex + 1); + + // + result = isFastUnderSlow && + !isPFastUnderSlow; + + // + return result; + } + + /** + * Check MA Fast is Crossed Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastOverLast = IsMAFastOverLast(barIndex); + bool isPFastOverLast = IsMAFastOverLast(barIndex + 1); + + // + result = isFastOverLast && + !isPFastOverLast; + + // + return result; + } + + /** + * Check MA Fast is Crossed Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastUnderLast = IsMAFastUnderLast(barIndex); + bool isPFastUnderLast = IsMAFastUnderLast(barIndex + 1); + + // + result = isFastUnderLast && + !isPFastUnderLast; + + // + return result; + } + + /** + * Check MA Slow is Crossed Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowCrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isSlowOverLast = IsMASlowOverLast(barIndex); + bool isPSlowOverLast = IsMASlowOverLast(barIndex + 1); + + // + result = isSlowOverLast && + !isPSlowOverLast; + + // + return result; + } + + /** + * Check MA Slow is Crossed Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowCrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isSlowUnderLast = IsMASlowUnderLast(barIndex); + bool isPSlowUnderLast = IsMASlowUnderLast(barIndex + 1); + + // + result = isSlowUnderLast && + !isPSlowUnderLast; + + // + return result; + } + + /** + * Check MA Fast and Slow Crossed Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMACrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastCrossedOverLast = IsMAFastCrossedOverLast(barIndex); + bool isSlowCrossedOverLast = IsMASlowCrossedOverLast(barIndex); + + // + result = isFastCrossedOverLast && + isSlowCrossedOverLast; + + // + return result; + } + + /** + * Check MA Fast and Slow Crossed Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMACrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastCrossedUnderLast = IsMAFastCrossedUnderLast(barIndex); + bool isSlowCrossedUnderLast = IsMASlowCrossedUnderLast(barIndex); + + // + result = isFastCrossedUnderLast && + isSlowCrossedUnderLast; + + // + return result; + } + + /** + * Count MA Fast Over Slows ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastOverSlows( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastOverSlow(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Fast Under Slows ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastUnderSlows( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastUnderSlow(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Fast Over Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastOverLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastOverLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Fast Under Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastUnderLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastUnderLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Slow Over Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMASlowOverLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMASlowOverLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Slow Under Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMASlowUnderLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMASlowUnderLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Over MA Fast Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverMAFastBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMAFast(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under MA Fast Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderMAFastBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMAFast(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Over MA Slow Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverMASlowBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMASlow(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under MA Slow Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderMASlowBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMASlow(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + // + // XHK ... + + /** + * Check HK is Bullish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iO = helper.GetHKOpen(barIndex); + double iC = helper.GetHKClose(barIndex); + + // + result = + NotEmptyZero(iO) && + NotEmptyZero(iC) && + iC > iO; + + // + return result; + } + + /** + * Check HK is Bearish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iO = helper.GetHKOpen(barIndex); + double iC = helper.GetHKClose(barIndex); + + // + result = + NotEmptyZero(iO) && + NotEmptyZero(iC) && + iC < iO; + + // + return result; + } + + /** + * Check HK is Switched to Bullish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool is = IsHKBullish(barIndex); + bool isP = IsHKBullish(barIndex + 1); + + // + result = is && + !isP; + + // + return result; + } + + /** + * Check HK is Switched to Bearish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool is = IsHKBearish(barIndex); + bool isP = IsHKBearish(barIndex + 1); + + // + result = is && + !isP; + + // + return result; + } + + /** + * Check Price is Over HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandLower(barIndex); + result = + result && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Over HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandUpper(barIndex); + result = + result && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandLower(barIndex); + result = + result && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandUpper(barIndex); + result = + result && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price Crossed Over HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverHKBandLower(barIndex, priceType); + bool isP = IsOverHKBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price Crossed Under HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderHKBandLower(barIndex, priceType); + bool isP = IsUnderHKBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price Crossed Over HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverHKBandUpper(barIndex, priceType); + bool isP = IsOverHKBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price Crossed Under HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderHKBandUpper(barIndex, priceType); + bool isP = IsUnderHKBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Count Bullish HK(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishHKs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHKBullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish HK(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishHKs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHKBearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + // + // XPV ... + + /** + * Check Peak Same as Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = helper.GetPeak(barIndex); + double iP = helper.GetPeak(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + /** + * Check Vale Same as Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = helper.GetVale(barIndex); + double iP = helper.GetVale(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + /** + * Count Same Peaks ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSamePeaks( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double peak = helper.GetPeak(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iPeak = helper.GetPeak(idx); + has = peak == iPeak; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Same Vales ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSameVales( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iVale = EMPTY_VALUE; + double vale = helper.GetVale(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iVale = helper.GetVale(idx); + has = vale == iVale; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Check Peak Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = helper.GetPeak(barIndex); + double pPeak = helper.GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak > pPeak; + + // + return result; + } + + /** + * Check Vale Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = helper.GetVale(barIndex); + double pVale = helper.GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale > pVale; + + // + return result; + } + + /** + * Check Peak Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = helper.GetPeak(barIndex); + double pPeak = helper.GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak < pPeak; + + // + return result; + } + + /** + * Check Vale Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = helper.GetVale(barIndex); + double pVale = helper.GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale < pVale; + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + // XZG ... + + /** + * Check ZigZag has Value and Read it ... + * + * @param value: double, reference to holds value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasZG( + double &value, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + value = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + value = helper.GetZigZag(barIndex); + + // + result = NotEmptyZero(value); + + // + return result; + } + + /** + * Check ZG is Low or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsZGLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Reading Value ... + double iValue; + result = HasZG(iValue, barIndex); + if (!result) + { + return result; + } + + // + // Reading Value ... + XOHCL iBar; + result = iBar.Init(symbol, period, barIndex); + result = result && + iBar.low == iValue; + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Check ZG is High or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsZGHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Reading Value ... + double iValue; + result = HasZG(iValue, barIndex); + if (!result) + { + return result; + } + + // + // Reading Value ... + XOHCL iBar; + result = iBar.Init(symbol, period, barIndex); + result = result && + iBar.high == iValue; + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + // + // XATR ... + + bool GetATRBox( + XBoxZone &zone, + int barIndex = 0, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double lowers[]; + double uppers[]; + double iUpper = EMPTY_VALUE; + double iLower = EMPTY_VALUE; + double upper = helper.GetATRRawBandUpper(barIndex); + double lower = helper.GetATRRawBandLower(barIndex); + int idx = barIndex; + while (idx <= barIndex + loopback) + { + // + idx++; + iUpper = helper.GetATRRawBandUpper(idx); + iLower = helper.GetATRRawBandLower(idx); + Add(iUpper, uppers); + Add(iLower, lowers); + } + + // + zone.symbol = symbol; + zone.period = period; + zone.upper = GetMax(uppers); + zone.lower = GetMin(lowers); + zone.dir = + (upper > zone.upper || + lower > zone.lower) + ? X_DIRECTION_BULLISH + : (upper < zone.upper || + lower < zone.lower) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(XFIMA_PIVOT_ATR); + zone.to = GetBarTime(symbol, period, barIndex); + zone.at = zone.to; + zone.from = GetBarTime(symbol, period, barIndex + loopback); + + // + result = zone.IsValid(); + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Check Price is Over ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandLower(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Over ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandUpper(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandLower(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandUpper(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Crossed Over ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverATRBandLower(barIndex, priceType); + bool isP = IsOverATRBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price is Crossed Under ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderATRBandLower(barIndex, priceType); + bool isP = IsUnderATRBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price is Crossed Over ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverATRBandUpper(barIndex, priceType); + bool isP = IsOverATRBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price is Crossed Under ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderATRBandUpper(barIndex, priceType); + bool isP = IsUnderATRBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + // + // Cycles Tools ... + + // + // SC ... + + /** + * Check Short Cycle is Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMABullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetSCMAState(barIndex); + + // + result = state >= 1; + + // + return result; + } + + /** + * Check Short Cycle is Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMABearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetSCMAState(barIndex); + + // + result = state <= -1; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMASwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsSCMABullish(barIndex); + bool isP = IsSCMABullish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMASwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsSCMABearish(barIndex); + bool isP = IsSCMABearish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Count Bullish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishSCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSCMABullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishSCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSCMABearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last MA Bullish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSCMASwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSCMASwitchedToBullish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last MA Bearish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSCMASwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSCMASwitchedToBearish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle MA Happens Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMAOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSCMA(barIndex); + double pValue = helper.GetSCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue > pValue; + + // + return result; + } + + /** + * Check Cycle MA Happens Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMAUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSCMA(barIndex); + double pValue = helper.GetSCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue < pValue; + + // + return result; + } + + /** + * Check Cycle MA Crossed Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMACrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsSCMAOverLast(barIndex); + bool isP = IsSCMAOverLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle MA Crossed Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCMACrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsSCMAUnderLast(barIndex); + bool isP = IsSCMAUnderLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle Lows is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCLLSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSLL(barIndex); + double pValue = helper.GetSLL(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Lower Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCLowerLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSLL(barIndex); + double pValue = helper.GetSLL(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Higher Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCHigherLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSLL(barIndex); + double pValue = helper.GetSLL(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCHHSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSHH(barIndex); + double pValue = helper.GetSHH(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Lower High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCLowerHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSHH(barIndex); + double pValue = helper.GetSHH(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Higher High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSCHigherHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetSHH(barIndex); + double pValue = helper.GetSHH(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Count Cycle Same LL(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSCSameLLs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSCLLSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Cycle Same HH(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSCSameHHs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSCHHSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last Cycle Lower Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSCLowerLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSCLowerLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSCHigherLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSCHigherLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Lower High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSCLowerHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSCLowerHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSCHigherHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSCHigherHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle Has Trend or not ... + * + * @param trend: XTrend, reference to holds Detected Trend ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool HasSCTrend( + XTrend &trend, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + trend.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Detecte Lower Lows ... + int cLowerLowIDX = -1; + int pLowerLowIDX = -1; + bool hasCLowerLow = FindLastSCLowerLow(cLowerLowIDX, barIndex, loopback); + bool hasPLowerLow = + hasCLowerLow && + FindLastSCLowerLow(pLowerLowIDX, cLowerLowIDX, loopback); + + // + // Detect Lower Highs ... + int cLowerHighIDX = -1; + int pLowerHighIDX = -1; + bool hasCLowerHigh = FindLastSCLowerHigh(cLowerHighIDX, barIndex, loopback); + bool hasPLowerHigh = + hasCLowerHigh && + FindLastSCLowerHigh(pLowerHighIDX, cLowerHighIDX, loopback); + + // + // Detect Higher Lows ... + int cHigherLowIDX = -1; + int pHigherLowIDX = -1; + bool hasCHigherLow = FindLastSCHigherLow(cHigherLowIDX, barIndex, loopback); + bool hasPHigherLow = + hasCHigherLow && + FindLastSCHigherLow(pHigherLowIDX, cHigherLowIDX, loopback); + + // + // Detect Higher Highs ... + int cHigherHighIDX = -1; + int pHigherHighIDX = -1; + bool hasCHigherHigh = FindLastSCHigherHigh(cHigherHighIDX, barIndex, loopback); + bool hasPHigherHigh = + hasCHigherHigh && + FindLastSCHigherHigh(pHigherHighIDX, cHigherHighIDX, loopback); + + // + // Detect Direction ... + + // + // Bullish ... + bool isBullish = + hasCHigherLow && + hasPHigherLow && + hasCHigherHigh && + hasPHigherHigh; + + // + // Bearish ... + bool isBearish = + hasCLowerLow && + hasPLowerLow && + hasCLowerHigh && + hasPLowerHigh; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Preparing XTrend ... + if (result) + { + // + // Define Requirements ... + + // + datetime toTime = NULL; + datetime fromTime = NULL; + + // + double toValue = EMPTY_VALUE; + double fromValue = EMPTY_VALUE; + + // + // Validating Directions ... + + // + // Bullish Validation ... + if (isBullish) + { + // + datetime cHL = GetBarTime(symbol, period, cHigherLowIDX); + datetime pHL = GetBarTime(symbol, period, pHigherLowIDX); + + // + toTime = cHL; + fromTime = pHL; + + // + toValue = helper.GetSLL(cHigherLowIDX); + fromValue = helper.GetSLL(pHigherLowIDX); + + // + // Validate Conditions ... + isBullish = + isBullish && + fromValue < toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Bearish Validation ... + if (isBearish) + { + // + datetime cLH = GetBarTime(symbol, period, cLowerHighIDX); + datetime pLH = GetBarTime(symbol, period, pLowerHighIDX); + + // + toTime = cLH; + fromTime = pLH; + + // + toValue = helper.GetSHH(cLowerHighIDX); + fromValue = helper.GetSHH(pLowerHighIDX); + + // + // Validate Conditions ... + isBearish = + isBearish && + fromValue > toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Validate Values ... + result = + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + + // + // Try to Initialized Trend ... + if (result) + { + // + // Initialize Trend ... + result = trend.Init( + symbol, + period, + TimeCurrent(), + fromValue, + fromTime, + toValue, + toTime // + ); + } + + // + // Validate Trend ... + result = trend.IsValid(); + } + + // + // Validate Result ... + result = trend.IsValid() && + trend.HasTrend(); + + // + // Cleanup ... + if (!result) + { + trend.Clean(); + } + + // + return result; + } + + // + // MC ... + + /** + * Check Short Cycle is Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMABullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetMCMAState(barIndex); + + // + result = state >= 1; + + // + return result; + } + + /** + * Check Short Cycle is Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMABearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetMCMAState(barIndex); + + // + result = state <= -1; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMASwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMCMABullish(barIndex); + bool isP = IsMCMABullish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMASwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMCMABearish(barIndex); + bool isP = IsMCMABearish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Count Bullish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishMCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMCMABullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishMCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMCMABearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last MA Bullish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastMCMASwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsMCMASwitchedToBullish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last MA Bearish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastMCMASwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsMCMASwitchedToBearish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle MA Happens Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMAOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMCMA(barIndex); + double pValue = helper.GetMCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue > pValue; + + // + return result; + } + + /** + * Check Cycle MA Happens Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMAUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMCMA(barIndex); + double pValue = helper.GetMCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue < pValue; + + // + return result; + } + + /** + * Check Cycle MA Crossed Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMACrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMCMAOverLast(barIndex); + bool isP = IsMCMAOverLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle MA Crossed Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCMACrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsMCMAUnderLast(barIndex); + bool isP = IsMCMAUnderLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle Lows is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCLLSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMLL(barIndex); + double pValue = helper.GetMLL(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Lower Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCLowerLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMLL(barIndex); + double pValue = helper.GetMLL(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Higher Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCHigherLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMLL(barIndex); + double pValue = helper.GetMLL(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCHHSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMHH(barIndex); + double pValue = helper.GetMHH(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Lower High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCLowerHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMHH(barIndex); + double pValue = helper.GetMHH(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Higher High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMCHigherHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetMHH(barIndex); + double pValue = helper.GetMHH(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Count Cycle Same LL(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMCSameLLs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMCLLSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Cycle Same HH(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMCSameHHs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMCHHSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last Cycle Lower Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastMCLowerLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsMCLowerLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastMCHigherLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsMCHigherLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Lower High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastMCLowerHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsMCLowerHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastMCHigherHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsMCHigherHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle Has Trend or not ... + * + * @param trend: XTrend, reference to holds Detected Trend ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool HasMCTrend( + XTrend &trend, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + trend.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Detecte Lower Lows ... + int cLowerLowIDX = -1; + int pLowerLowIDX = -1; + bool hasCLowerLow = FindLastMCLowerLow(cLowerLowIDX, barIndex, loopback); + bool hasPLowerLow = + hasCLowerLow && + FindLastMCLowerLow(pLowerLowIDX, cLowerLowIDX, loopback); + + // + // Detect Lower Highs ... + int cLowerHighIDX = -1; + int pLowerHighIDX = -1; + bool hasCLowerHigh = FindLastMCLowerHigh(cLowerHighIDX, barIndex, loopback); + bool hasPLowerHigh = + hasCLowerHigh && + FindLastMCLowerHigh(pLowerHighIDX, cLowerHighIDX, loopback); + + // + // Detect Higher Lows ... + int cHigherLowIDX = -1; + int pHigherLowIDX = -1; + bool hasCHigherLow = FindLastMCHigherLow(cHigherLowIDX, barIndex, loopback); + bool hasPHigherLow = + hasCHigherLow && + FindLastMCHigherLow(pHigherLowIDX, cHigherLowIDX, loopback); + + // + // Detect Higher Highs ... + int cHigherHighIDX = -1; + int pHigherHighIDX = -1; + bool hasCHigherHigh = FindLastMCHigherHigh(cHigherHighIDX, barIndex, loopback); + bool hasPHigherHigh = + hasCHigherHigh && + FindLastMCHigherHigh(pHigherHighIDX, cHigherHighIDX, loopback); + + // + // Detect Direction ... + + // + // Bullish ... + bool isBullish = + hasCHigherLow && + hasPHigherLow && + hasCHigherHigh && + hasPHigherHigh; + + // + // Bearish ... + bool isBearish = + hasCLowerLow && + hasPLowerLow && + hasCLowerHigh && + hasPLowerHigh; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Preparing XTrend ... + if (result) + { + // + // Define Requirements ... + + // + datetime toTime = NULL; + datetime fromTime = NULL; + + // + double toValue = EMPTY_VALUE; + double fromValue = EMPTY_VALUE; + + // + // Validating Directions ... + + // + // Bullish Validation ... + if (isBullish) + { + // + datetime cHL = GetBarTime(symbol, period, cHigherLowIDX); + datetime pHL = GetBarTime(symbol, period, pHigherLowIDX); + + // + toTime = cHL; + fromTime = pHL; + + // + toValue = helper.GetMLL(cHigherLowIDX); + fromValue = helper.GetMLL(pHigherLowIDX); + + // + // Validate Conditions ... + isBullish = + isBullish && + fromValue < toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Bearish Validation ... + if (isBearish) + { + // + datetime cLH = GetBarTime(symbol, period, cLowerHighIDX); + datetime pLH = GetBarTime(symbol, period, pLowerHighIDX); + + // + toTime = cLH; + fromTime = pLH; + + // + toValue = helper.GetMHH(cLowerHighIDX); + fromValue = helper.GetMHH(pLowerHighIDX); + + // + // Validate Conditions ... + isBearish = + isBearish && + fromValue > toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Validate Values ... + result = + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + + // + // Try to Initialized Trend ... + if (result) + { + // + // Initialize Trend ... + result = trend.Init( + symbol, + period, + TimeCurrent(), + fromValue, + fromTime, + toValue, + toTime // + ); + } + + // + // Validate Trend ... + result = trend.IsValid(); + } + + // + // Validate Result ... + result = trend.IsValid() && + trend.HasTrend(); + + // + // Cleanup ... + if (!result) + { + trend.Clean(); + } + + // + return result; + } + + // + // LC ... + + /** + * Check Short Cycle is Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMABullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetLCMAState(barIndex); + + // + result = state >= 1; + + // + return result; + } + + /** + * Check Short Cycle is Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMABearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetLCMAState(barIndex); + + // + result = state <= -1; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMASwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsLCMABullish(barIndex); + bool isP = IsLCMABullish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMASwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsLCMABearish(barIndex); + bool isP = IsLCMABearish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Count Bullish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishLCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsLCMABullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishLCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsLCMABearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last MA Bullish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastLCMASwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsLCMASwitchedToBullish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last MA Bearish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastLCMASwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsLCMASwitchedToBearish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle MA Happens Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMAOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLCMA(barIndex); + double pValue = helper.GetLCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue > pValue; + + // + return result; + } + + /** + * Check Cycle MA Happens Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMAUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLCMA(barIndex); + double pValue = helper.GetLCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue < pValue; + + // + return result; + } + + /** + * Check Cycle MA Crossed Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMACrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsLCMAOverLast(barIndex); + bool isP = IsLCMAOverLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle MA Crossed Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCMACrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsLCMAUnderLast(barIndex); + bool isP = IsLCMAUnderLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle Lows is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCLLSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLLL(barIndex); + double pValue = helper.GetLLL(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Lower Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCLowerLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLLL(barIndex); + double pValue = helper.GetLLL(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Higher Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCHigherLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLLL(barIndex); + double pValue = helper.GetLLL(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCHHSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLHH(barIndex); + double pValue = helper.GetLHH(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Lower High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCLowerHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLHH(barIndex); + double pValue = helper.GetLHH(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Higher High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsLCHigherHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetLHH(barIndex); + double pValue = helper.GetLHH(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Count Cycle Same LL(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountLCSameLLs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsLCLLSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Cycle Same HH(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountLCSameHHs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsLCHHSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last Cycle Lower Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastLCLowerLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsLCLowerLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastLCHigherLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsLCHigherLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Lower High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastLCLowerHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsLCLowerHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastLCHigherHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsLCHigherHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle Has Trend or not ... + * + * @param trend: XTrend, reference to holds Detected Trend ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool HasLCTrend( + XTrend &trend, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + trend.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Detecte Lower Lows ... + int cLowerLowIDX = -1; + int pLowerLowIDX = -1; + bool hasCLowerLow = FindLastLCLowerLow(cLowerLowIDX, barIndex, loopback); + bool hasPLowerLow = + hasCLowerLow && + FindLastLCLowerLow(pLowerLowIDX, cLowerLowIDX, loopback); + + // + // Detect Lower Highs ... + int cLowerHighIDX = -1; + int pLowerHighIDX = -1; + bool hasCLowerHigh = FindLastLCLowerHigh(cLowerHighIDX, barIndex, loopback); + bool hasPLowerHigh = + hasCLowerHigh && + FindLastLCLowerHigh(pLowerHighIDX, cLowerHighIDX, loopback); + + // + // Detect Higher Lows ... + int cHigherLowIDX = -1; + int pHigherLowIDX = -1; + bool hasCHigherLow = FindLastLCHigherLow(cHigherLowIDX, barIndex, loopback); + bool hasPHigherLow = + hasCHigherLow && + FindLastLCHigherLow(pHigherLowIDX, cHigherLowIDX, loopback); + + // + // Detect Higher Highs ... + int cHigherHighIDX = -1; + int pHigherHighIDX = -1; + bool hasCHigherHigh = FindLastLCHigherHigh(cHigherHighIDX, barIndex, loopback); + bool hasPHigherHigh = + hasCHigherHigh && + FindLastLCHigherHigh(pHigherHighIDX, cHigherHighIDX, loopback); + + // + // Detect Direction ... + + // + // Bullish ... + bool isBullish = + hasCHigherLow && + hasPHigherLow && + hasCHigherHigh && + hasPHigherHigh; + + // + // Bearish ... + bool isBearish = + hasCLowerLow && + hasPLowerLow && + hasCLowerHigh && + hasPLowerHigh; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Preparing XTrend ... + if (result) + { + // + // Define Requirements ... + + // + datetime toTime = NULL; + datetime fromTime = NULL; + + // + double toValue = EMPTY_VALUE; + double fromValue = EMPTY_VALUE; + + // + // Validating Directions ... + + // + // Bullish Validation ... + if (isBullish) + { + // + datetime cHL = GetBarTime(symbol, period, cHigherLowIDX); + datetime pHL = GetBarTime(symbol, period, pHigherLowIDX); + + // + toTime = cHL; + fromTime = pHL; + + // + toValue = helper.GetLLL(cHigherLowIDX); + fromValue = helper.GetLLL(pHigherLowIDX); + + // + // Validate Conditions ... + isBullish = + isBullish && + fromValue < toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Bearish Validation ... + if (isBearish) + { + // + datetime cLH = GetBarTime(symbol, period, cLowerHighIDX); + datetime pLH = GetBarTime(symbol, period, pLowerHighIDX); + + // + toTime = cLH; + fromTime = pLH; + + // + toValue = helper.GetLHH(cLowerHighIDX); + fromValue = helper.GetLHH(pLowerHighIDX); + + // + // Validate Conditions ... + isBearish = + isBearish && + fromValue > toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Validate Values ... + result = + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + + // + // Try to Initialized Trend ... + if (result) + { + // + // Initialize Trend ... + result = trend.Init( + symbol, + period, + TimeCurrent(), + fromValue, + fromTime, + toValue, + toTime // + ); + } + + // + // Validate Trend ... + result = trend.IsValid(); + } + + // + // Validate Result ... + result = trend.IsValid() && + trend.HasTrend(); + + // + // Cleanup ... + if (!result) + { + trend.Clean(); + } + + // + return result; + } + + // + // HC ... + + /** + * Check Short Cycle is Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMABullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetHCMAState(barIndex); + + // + result = state >= 1; + + // + return result; + } + + /** + * Check Short Cycle is Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMABearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetHCMAState(barIndex); + + // + result = state <= -1; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bullish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMASwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsHCMABullish(barIndex); + bool isP = IsHCMABullish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Short Cycle is Switched to Bearish ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMASwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsHCMABearish(barIndex); + bool isP = IsHCMABearish(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Count Bullish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishHCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHCMABullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish MA(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishHCMAs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHCMABearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last MA Bullish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastHCMASwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsHCMASwitchedToBullish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last MA Bearish Switches ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastHCMASwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsHCMASwitchedToBearish(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle MA Happens Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMAOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHCMA(barIndex); + double pValue = helper.GetHCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue > pValue; + + // + return result; + } + + /** + * Check Cycle MA Happens Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMAUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHCMA(barIndex); + double pValue = helper.GetHCMA(barIndex + 1); + + // + result = + NotEmptyZero(cValue) && + NotEmptyZero(pValue) && + cValue < pValue; + + // + return result; + } + + /** + * Check Cycle MA Crossed Over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMACrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsHCMAOverLast(barIndex); + bool isP = IsHCMAOverLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle MA Crossed Under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCMACrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isC = IsHCMAUnderLast(barIndex); + bool isP = IsHCMAUnderLast(barIndex + 1); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Cycle Lows is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCLLSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHLL(barIndex); + double pValue = helper.GetHLL(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Lower Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCLowerLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHLL(barIndex); + double pValue = helper.GetHLL(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Lows is Higher Low ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCHigherLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHLL(barIndex); + double pValue = helper.GetHLL(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Same ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCHHSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHHH(barIndex); + double pValue = helper.GetHHH(barIndex + 1); + + // + result = cValue == pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Lower High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCLowerHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHHH(barIndex); + double pValue = helper.GetHHH(barIndex + 1); + + // + result = cValue < pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Check Cycle Highss is Higher High ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsHCHigherHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double cValue = helper.GetHHH(barIndex); + double pValue = helper.GetHHH(barIndex + 1); + + // + result = cValue > pValue && + NotEmptyZero(cValue) && + NotEmptyZero(pValue); + + // + return result; + } + + /** + * Count Cycle Same LL(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountHCSameLLs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHCLLSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Cycle Same HH(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountHCSameHHs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHCHHSame(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Detect Last Cycle Lower Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastHCLowerLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsHCLowerLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher Low ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastHCHigherLow( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsHCHigherLow(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Lower High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastHCLowerHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsHCLowerHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Cycle Higher High ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastHCHigherHigh( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsHCHigherHigh(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Check Cycle Has Trend or not ... + * + * @param trend: XTrend, reference to holds Detected Trend ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool HasHCTrend( + XTrend &trend, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + trend.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Detecte Lower Lows ... + int cLowerLowIDX = -1; + int pLowerLowIDX = -1; + bool hasCLowerLow = FindLastHCLowerLow(cLowerLowIDX, barIndex, loopback); + bool hasPLowerLow = + hasCLowerLow && + FindLastHCLowerLow(pLowerLowIDX, cLowerLowIDX, loopback); + + // + // Detect Lower Highs ... + int cLowerHighIDX = -1; + int pLowerHighIDX = -1; + bool hasCLowerHigh = FindLastHCLowerHigh(cLowerHighIDX, barIndex, loopback); + bool hasPLowerHigh = + hasCLowerHigh && + FindLastHCLowerHigh(pLowerHighIDX, cLowerHighIDX, loopback); + + // + // Detect Higher Lows ... + int cHigherLowIDX = -1; + int pHigherLowIDX = -1; + bool hasCHigherLow = FindLastHCHigherLow(cHigherLowIDX, barIndex, loopback); + bool hasPHigherLow = + hasCHigherLow && + FindLastHCHigherLow(pHigherLowIDX, cHigherLowIDX, loopback); + + // + // Detect Higher Highs ... + int cHigherHighIDX = -1; + int pHigherHighIDX = -1; + bool hasCHigherHigh = FindLastHCHigherHigh(cHigherHighIDX, barIndex, loopback); + bool hasPHigherHigh = + hasCHigherHigh && + FindLastHCHigherHigh(pHigherHighIDX, cHigherHighIDX, loopback); + + // + // Detect Direction ... + + // + // Bullish ... + bool isBullish = + hasCHigherLow && + hasPHigherLow && + hasCHigherHigh && + hasPHigherHigh; + + // + // Bearish ... + bool isBearish = + hasCLowerLow && + hasPLowerLow && + hasCLowerHigh && + hasPLowerHigh; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Preparing XTrend ... + if (result) + { + // + // Define Requirements ... + + // + datetime toTime = NULL; + datetime fromTime = NULL; + + // + double toValue = EMPTY_VALUE; + double fromValue = EMPTY_VALUE; + + // + // Validating Directions ... + + // + // Bullish Validation ... + if (isBullish) + { + // + datetime cHL = GetBarTime(symbol, period, cHigherLowIDX); + datetime pHL = GetBarTime(symbol, period, pHigherLowIDX); + + // + toTime = cHL; + fromTime = pHL; + + // + toValue = helper.GetHLL(cHigherLowIDX); + fromValue = helper.GetHLL(pHigherLowIDX); + + // + // Validate Conditions ... + isBullish = + isBullish && + fromValue < toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Bearish Validation ... + if (isBearish) + { + // + datetime cLH = GetBarTime(symbol, period, cLowerHighIDX); + datetime pLH = GetBarTime(symbol, period, pLowerHighIDX); + + // + toTime = cLH; + fromTime = pLH; + + // + toValue = helper.GetHHH(cLowerHighIDX); + fromValue = helper.GetHHH(pLowerHighIDX); + + // + // Validate Conditions ... + isBearish = + isBearish && + fromValue > toValue && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + } + + // + // Validate Values ... + result = + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue); + + // + // Try to Initialized Trend ... + if (result) + { + // + // Initialize Trend ... + result = trend.Init( + symbol, + period, + TimeCurrent(), + fromValue, + fromTime, + toValue, + toTime // + ); + } + + // + // Validate Trend ... + result = trend.IsValid(); + } + + // + // Validate Result ... + result = trend.IsValid() && + trend.HasTrend(); + + // + // Cleanup ... + if (!result) + { + trend.Clean(); + } + + // + return result; + } + + /** + * Retrieve Cycles MA(s) ... + * + * @param scMA: double, reference to holds cycle value ... + * @param mcMA: double, reference to holds cycle value ... + * @param lcMA: double, reference to holds cycle value ... + * @param hcMA: double, reference to holds cycle value ... + * @param barIndex: int, Specified Bar Index ... + */ + void GetCycleMAs( + double &scMA, + double &mcMA, + double &lcMA, + double &hcMA, + int barIndex = 0 // + ) + { + // + // Prepare ... + scMA = EMPTY_VALUE; + mcMA = EMPTY_VALUE; + lcMA = EMPTY_VALUE; + hcMA = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return; + } + + // + scMA = helper.GetSCMA(barIndex); + mcMA = helper.GetMCMA(barIndex); + lcMA = helper.GetLCMA(barIndex); + hcMA = helper.GetHCMA(barIndex); + } + + /** + * Retrieve Cycles MA State(s) ... + * + * @param scMAState: double, reference to holds cycle value ... + * @param mcMAState: double, reference to holds cycle value ... + * @param lcMAState: double, reference to holds cycle value ... + * @param hcMAState: double, reference to holds cycle value ... + * @param barIndex: int, Specified Bar Index ... + */ + void GetCycleMAStates( + double &scMAState, + double &mcMAState, + double &lcMAState, + double &hcMAState, + int barIndex = 0 // + ) + { + // + // Prepare ... + scMAState = EMPTY_VALUE; + mcMAState = EMPTY_VALUE; + lcMAState = EMPTY_VALUE; + hcMAState = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return; + } + + // + scMAState = helper.GetSCMAState(barIndex); + mcMAState = helper.GetMCMAState(barIndex); + lcMAState = helper.GetLCMAState(barIndex); + hcMAState = helper.GetHCMAState(barIndex); + } + + /** + * Check Cycle Hind and Long is Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsCycleMABullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + IsLCMABullish(barIndex) && + IsHCMABullish(barIndex); + + // + return result; + } + + /** + * Check Cycle Hind and Long is Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsCycleMABearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + IsLCMABearish(barIndex) && + IsHCMABearish(barIndex); + + // + return result; + } + + // + // Boundary Tools ... + // ============================= + // Boundary Includes: + // MA Band ... + // PB Band ... + // HK Band ... + // ATR Band ... + + /** + * Reading Boundary Values ... + * + * @param maBandUpper: double, reference to holds MA Band Upper value ... + * @param maBandLower: double, reference to holds MA Band Lower value ... + * @param pbBandUpper: double, reference to holds PB Band Upper value ... + * @param pbBandLower: double, reference to holds PB Band Lower value ... + * @param hkBandUpper: double, reference to holds HK Band Upper value ... + * @param hkBandLower: double, reference to holds HK Band Lower value ... + * @param atrBandUpper: double, reference to holds ATR Band Upper value ... + * @param atrBandLower: double, reference to holds ATR Band Lower value ... + * @param barIndex: int, Specified Bar Index ... + */ + void GetBoundaryValues( + double &maBandUpper, + double &maBandLower, + double &pbBandUpper, + double &pbBandLower, + double &hkBandUpper, + double &hkBandLower, + double &atrBandUpper, + double &atrBandLower, + int barIndex = 0 // + ) + { + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Prepare ... + maBandUpper = EMPTY_VALUE; + maBandLower = EMPTY_VALUE; + pbBandUpper = EMPTY_VALUE; + pbBandLower = EMPTY_VALUE; + hkBandUpper = EMPTY_VALUE; + hkBandLower = EMPTY_VALUE; + atrBandUpper = EMPTY_VALUE; + atrBandLower = EMPTY_VALUE; + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return; + } + + // + maBandUpper = helper.GetMABandUpper(barIndex); + maBandLower = helper.GetMABandLower(barIndex); + pbBandUpper = helper.GetPBBandUpper(barIndex); + pbBandLower = helper.GetPBBandLower(barIndex); + hkBandUpper = helper.GetHKBandUpper(barIndex); + hkBandLower = helper.GetHKBandLower(barIndex); + atrBandUpper = helper.GetATRBandUpper(barIndex); + atrBandLower = helper.GetATRBandLower(barIndex); + } + + /** + * Read Boundary Values and Fill as an Array ... + * + * @param values: double, collection reference to fill results ... + * @param barIndex: int, Specified Bar Index ... + */ + void GetBoundaryValuesArray( + double &values[], + int barIndex = 0 // + ) + { + // + // Prepare ... + XClean(values); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return; + } + + // + // Reading Boundary Values ... + + // + double maBandUpper = EMPTY_VALUE; + double maBandLower = EMPTY_VALUE; + double pbBandUpper = EMPTY_VALUE; + double pbBandLower = EMPTY_VALUE; + double hkBandUpper = EMPTY_VALUE; + double hkBandLower = EMPTY_VALUE; + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + + // + GetBoundaryValues( + maBandUpper, + maBandLower, + pbBandUpper, + pbBandLower, + hkBandUpper, + hkBandLower, + atrBandUpper, + atrBandLower, + barIndex // + ); + + // + // Validate ... + has = + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower) && + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower); + if (!has) + { + return; + } + + // + Add(maBandUpper, values); + Add(maBandLower, values); + Add(pbBandUpper, values); + Add(pbBandLower, values); + Add(hkBandUpper, values); + Add(hkBandLower, values); + Add(atrBandUpper, values); + Add(atrBandLower, values); + } + + /** + * Read Boundary Min Value ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( double ) + */ + double GetBoundaryMin(int barIndex = 0) + { + // + double result = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double values[]; + GetBoundaryValuesArray(values, barIndex); + result = GetMin(values); + + // + return result; + } + + /** + * Read Boundary Max Value ... + * + * @param barIndex: int, Specified BAr Index ... + * + * @return ( double ) + */ + double GetBoundaryMax(int barIndex = 0) + { + // + double result = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double values[]; + GetBoundaryValuesArray(values, barIndex); + result = GetMax(values); + + // + return result; + } + + // + // Bars and Boundary ... + + /** + * Check Bar's Price is Over Boundary Max or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarOverBoundaryMax( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + double price = EMPTY_VALUE; + double value = GetBoundaryMax(barIndex); + result = bar.Init(symbol, period, barIndex); + if (result) + { + price = bar.GetPrice(priceType); + } + result = bar.IsValid() && + NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Bar's Price is Over Boundary Min or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarOverBoundaryMin( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + double price = EMPTY_VALUE; + double value = GetBoundaryMin(barIndex); + result = bar.Init(symbol, period, barIndex); + if (result) + { + price = bar.GetPrice(priceType); + } + result = bar.IsValid() && + NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Bar's Price is Under Boundary Max or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarUnderBoundaryMax( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + double price = EMPTY_VALUE; + double value = GetBoundaryMax(barIndex); + result = bar.Init(symbol, period, barIndex); + if (result) + { + price = bar.GetPrice(priceType); + } + result = bar.IsValid() && + NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Bar's Price is Under Boundary Min or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarUnderBoundaryMin( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + double price = EMPTY_VALUE; + double value = GetBoundaryMin(barIndex); + result = bar.Init(symbol, period, barIndex); + if (result) + { + price = bar.GetPrice(priceType); + } + result = bar.IsValid() && + NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Bar's Price is Crossed Over Boundary Max or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarCrossedOverBoundaryMax( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsBarOverBoundaryMax(barIndex, priceType); + bool isP = IsBarOverBoundaryMax(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Bar's Price is Crossed Over Boundary Min or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarCrossedOverBoundaryMin( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsBarOverBoundaryMin(barIndex, priceType); + bool isP = IsBarOverBoundaryMin(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Bar's Price is Crossed Under Boundary Max or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarCrossedUnderBoundaryMax( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsBarUnderBoundaryMax(barIndex, priceType); + bool isP = IsBarUnderBoundaryMax(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Bar's Price is Crossed Under Boundary Min or not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsBarCrossedUnderBoundaryMin( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsBarUnderBoundaryMin(barIndex, priceType); + bool isP = IsBarUnderBoundaryMin(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Count Over Boundary Max Bar's Prices ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBarsOverBoundaryMax( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsBarOverBoundaryMax(idx); + if (!has) + { + break; + } + result++; + } + + // + return result; + } + + /** + * Count Over Boundary Min Bar's Prices ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBarsOverBoundaryMin( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsBarOverBoundaryMin(idx); + if (!has) + { + break; + } + result++; + } + + // + return result; + } + + /** + * Count Under Boundary Max Bar's Prices ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBarsUnderBoundaryMax( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsBarUnderBoundaryMax(idx); + if (!has) + { + break; + } + result++; + } + + // + return result; + } + + /** + * Count Under Boundary Min Bar's Prices ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBarsUnderBoundaryMin( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsBarUnderBoundaryMin(idx); + if (!has) + { + break; + } + result++; + } + + // + return result; + } + + /** + * Check Has Boundary Trend or not ... + * + * @param trend: XTrend, refrence to holds Detected trend ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasBoundaryTrend( + XTrend &trend, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + trend.Clean(); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + int pIDX = barIndex + 1; + + // + // Select Times ... + datetime toTime = GetBarTime(symbol, period, barIndex); + datetime fromTime = GetBarTime(symbol, period, pIDX); + + // + // Reading Min and Max ... + + // + double bMax = GetBoundaryMax(barIndex); + double pBMax = GetBoundaryMax(pIDX); + + // + double bMin = GetBoundaryMin(barIndex); + double pBMin = GetBoundaryMin(pIDX); + + // + bool isBullish = + pBMax < bMax && + pBMin < bMin; + + // + bool isBearish = + pBMax > bMax && + pBMin > bMin; + + // + // Initialize Trend ... + result = isBullish || isBearish; + if (result) + { + // + result = trend.Init( + symbol, + period, + toTime, + isBullish + ? pBMin + : pBMax, + fromTime, + isBullish + ? bMin + : bMax, + toTime // + ); + + // + if (!result) + { + trend.Clean(); + } + } + + // + result = trend.IsValid() && + trend.HasTrend(); + + // + // Cleanup ... + if (!result) + { + trend.Clean(); + } + + // + return result; + } + + // + // Other Tools ... + + /** + * Reading All Values of XFIMA ... + * + * @param dest: double, collection reference to holds values ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( int ) + */ + int ReadXFIMAValues( + double &dest[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Reading Values ... + double sar = helper.GetSAR(barIndex); + double scLL = helper.GetSLL(barIndex); + double scHH = helper.GetSHH(barIndex); + double mcLL = helper.GetMLL(barIndex); + double mcHH = helper.GetMHH(barIndex); + double lcLL = helper.GetLLL(barIndex); + double lcHH = helper.GetLHH(barIndex); + double hcLL = helper.GetHLL(barIndex); + double hcHH = helper.GetHHH(barIndex); + double peak = helper.GetPeak(barIndex); + double vale = helper.GetVale(barIndex); + double scMa = helper.GetSCMA(barIndex); + double mcMa = helper.GetMCMA(barIndex); + double lcMa = helper.GetLCMA(barIndex); + double hcMa = helper.GetHCMA(barIndex); + double maFast = helper.GetMAFast(barIndex); + double maSlow = helper.GetMASlow(barIndex); + double fibLower = helper.GetFiboLower(barIndex); + double fibUpper = helper.GetFiboUpper(barIndex); + double fibMiddle = helper.GetFiboMiddle(barIndex); + double maBandUpper = helper.GetMABandUpper(barIndex); + double maBandLower = helper.GetMABandLower(barIndex); + double hkBandUpper = helper.GetHKBandUpper(barIndex); + double hkBandLower = helper.GetHKBandLower(barIndex); + double pbBandUpper = helper.GetPBBandUpper(barIndex); + double pbBandLower = helper.GetPBBandLower(barIndex); + double atrBandUpper = helper.GetATRBandUpper(barIndex); + double atrBandLower = helper.GetATRBandLower(barIndex); + + // + // Add Values to Dest ... + + // + if (NotEmptyZero(sar)) + { + Add(sar, dest); + } + + // + if (NotEmptyZero(scLL)) + { + Add(scLL, dest); + } + + // + if (NotEmptyZero(scHH)) + { + Add(scHH, dest); + } + + // + if (NotEmptyZero(mcLL)) + { + Add(mcLL, dest); + } + + // + if (NotEmptyZero(mcHH)) + { + Add(mcHH, dest); + } + + // + if (NotEmptyZero(lcLL)) + { + Add(lcLL, dest); + } + + // + if (NotEmptyZero(lcHH)) + { + Add(lcHH, dest); + } + + // + if (NotEmptyZero(hcLL)) + { + Add(hcLL, dest); + } + + // + if (NotEmptyZero(hcHH)) + { + Add(hcHH, dest); + } + + // + if (NotEmptyZero(peak)) + { + Add(peak, dest); + } + + // + if (NotEmptyZero(vale)) + { + Add(vale, dest); + } + + // + if (NotEmptyZero(scMa)) + { + Add(scMa, dest); + } + + // + if (NotEmptyZero(mcMa)) + { + Add(mcMa, dest); + } + + // + if (NotEmptyZero(lcMa)) + { + Add(lcMa, dest); + } + + // + if (NotEmptyZero(hcMa)) + { + Add(hcMa, dest); + } + + // + if (NotEmptyZero(maFast)) + { + Add(maFast, dest); + } + + // + if (NotEmptyZero(maSlow)) + { + Add(maSlow, dest); + } + + // + if (NotEmptyZero(fibLower)) + { + Add(fibLower, dest); + } + + // + if (NotEmptyZero(fibUpper)) + { + Add(fibUpper, dest); + } + + // + if (NotEmptyZero(fibMiddle)) + { + Add(fibMiddle, dest); + } + + // + if (NotEmptyZero(maBandUpper)) + { + Add(maBandUpper, dest); + } + + // + if (NotEmptyZero(maBandLower)) + { + Add(maBandLower, dest); + } + + // + if (NotEmptyZero(hkBandUpper)) + { + Add(hkBandUpper, dest); + } + + // + if (NotEmptyZero(hkBandLower)) + { + Add(hkBandLower, dest); + } + + // + if (NotEmptyZero(pbBandUpper)) + { + Add(pbBandUpper, dest); + } + + // + if (NotEmptyZero(pbBandLower)) + { + Add(pbBandLower, dest); + } + + // + if (NotEmptyZero(atrBandUpper)) + { + Add(atrBandUpper, dest); + } + + // + if (NotEmptyZero(atrBandLower)) + { + Add(atrBandLower, dest); + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + XCXFIMAHelper *helper; + + // +}; + +// diff --git a/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 new file mode 100644 index 0000000..a28cf38 --- /dev/null +++ b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -0,0 +1,3174 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA 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 XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; + + // + has = iGuard.IsValid(); + if (has) + { + // + AddRef(iGuard, guards); + + // + // // + // // Remove TP if in Profit SL ... + // iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + // has = + // (positions[i].IsBullish() && HasResistance()) + // ? (iGuard.sl >= iValue && + // positions[i].tp < resistance.lower) + // : (positions[i].IsBearish() && HasSupport()) + // ? (iGuard.sl <= iValue && + // positions[i].tp > support.upper) + // : false; + // if (has) + // { + // // + // iGuard.Clean(); + // iGuard.force = false; + // iGuard.tp = positions[i].IsBullish() + // ? resistance.lower + // : support.upper; + // iGuard.time = TimeCurrent(); + // iGuard.symbol = positions[i].symbol; + // iGuard.period = positions[i].period; + // iGuard.ticket = positions[i].ticket; + // iGuard.provider = positions[i].provider; + // iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; + + // // + // has = iGuard.IsValid(); + // if (has) + // { + // AddRef(iGuard, guards); + // } + // } + } + } + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = true; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = false; + + // + XBoxZone tmpZone; + string provider = NULL; + ENUM_X_DIRECTION tmpDir; + + // + bool signaller1HasSignal = false; + bool signaller2HasSignal = false; + bool signaller3HasSignal = false; + bool signaller4HasSignal = false; + + // + // Validator Flags ... + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = false; + bool drawMarketStructureAnalysis = false; + bool drawMarketStructureOrderFlow = false; + XPOIDrawConfig iDrawConfig; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Signal Detection Flags ... + + // + // Signaller 1 ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += "1"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + if (useSignaller2) + { + // + signaller2HasSignal = Strategy2HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller2HasSignal) + { + // + provider += "2"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + if (useSignaller3) + { + // + signaller3HasSignal = Strategy3HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller3HasSignal) + { + // + provider += "3"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + if (useSignaller4) + { + // + signaller4HasSignal = Strategy4HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller4HasSignal) + { + // + provider += "4"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal; + + // + // Signal Validating ... + + // + // Validate Signals by Order Flow ... + if (result && validateByOrderFlow) + { + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + + // + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Prepare Draw Config ... + iDrawConfig = structureDrawConfig.drawConfig; + iDrawConfig.zonesWidth = 3; + iDrawConfig.zonesStyle = STYLE_DASH; + iDrawConfig.bullishColor = clrYellow; + iDrawConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (drawZone) + { + poiDrawer.DrawZone(zone, iDrawConfig); + } + + // + // Draw Market Structure ... + + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } + } + + // + // Other Drawing Materials ... + Print("Signaller Providers: ", provider); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + tmpZone.Clean(); + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validator Flags ... + bool validateByZones = false; + bool validateHasLiquidity = false; + bool validateByXFIMARejected = true; + bool validateByXFIMAMACrossed = false; + bool validateByCyclesMATresnding = false; + bool validateByHasDirectionalZones = false; + bool validateByHasInDirectionalZones = false; + bool validateByInDirectionalZonesPlacement = false; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XBoxZone zones[]; + double rejecteds[]; + XBoxZone liquidity; + bool isBullish = false; + bool isBearish = false; + XBoxZone directionalZone; + XBoxZone inDirectionalZone; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysis p3BarPatterns; + XPatternAnalysisConfig iPatternsConfig; + + // + // Reading Bars ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading Bar Patterns ... + iPatternsConfig.Default(); + iPatternsConfig.FullPattern(); + result = + result && + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + iPatternsConfig // + ); + result = + result && + poiDetector.AnalyseBarPatterns( + p3Bar, + p3BarPatterns, + iPatternsConfig // + ); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + iPatternsConfig.Clean(); + + // + return result; + } + + // + // Detect Pin Bar ... + bool isPBarIsPinBar = false && + poiDetector.IsPinnedBar( + pBar, + dir, + 3, + 4, + true // + ); + bool isPBarIsPinBarBullish = isPBarIsPinBar && IsXBullish(dir); + bool isPBarIsPinBarBearish = isPBarIsPinBar && IsXBearish(dir); + if (isPBarIsPinBar) + { + // + // Bullish ... + isPBarIsPinBarBullish = + isPBarIsPinBarBullish && + pBar.GetHighShadow() < pBar.GetBody(); + + // + // Bearish ... + isPBarIsPinBarBearish = + isPBarIsPinBarBearish && + pBar.GetLowShadow() < pBar.GetBody(); + + // + isPBarIsPinBar = isPBarIsPinBarBullish || isPBarIsPinBarBearish; + } + + // + // Detect Signal Key Bar ... + bool isPBarSignalKeyBar = poiDetector.IsSignalKeyBarPattern( + pBar, + dir, + 3, + 4, + true // + ); + bool isPBarSignalKeyBarBullish = isPBarSignalKeyBar && IsXBullish(dir); + bool isPBarSignalKeyBarBearish = isPBarSignalKeyBar && IsXBearish(dir); + if (isPBarSignalKeyBar) + { + // + // Bullish ... + isPBarSignalKeyBarBullish = + isPBarSignalKeyBarBullish && + p2Bar.GetHighShadow() < p2Bar.GetBody(); + + // + // Bearish ... + isPBarSignalKeyBarBearish = + isPBarSignalKeyBarBearish && + p2Bar.GetLowShadow() < p2Bar.GetBody(); + + // + isPBarSignalKeyBar = isPBarSignalKeyBarBullish || isPBarSignalKeyBarBearish; + } + + // + bool hasBullishBar = isPBarIsPinBarBullish || + isPBarSignalKeyBarBullish; + + // + bool hasBearishBar = isPBarIsPinBarBearish || + isPBarSignalKeyBarBearish; + + // + isBullish = hasBullishBar; + + // + isBearish = hasBearishBar; + + // + result = isBullish || isBearish; + + // + // Prepare Zone Based on Started Conditions ... + if (result) + { + // + zone.Clean(); + dir = hasBullishBar + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + if (isPBarIsPinBar) + { + // + result = ToBox( + pBar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + } + else if (isPBarSignalKeyBar) + { + // + result = ToBox( + pBar, + zone, + dir, + X_BAR_PATTERN_SIGNALKEY // + ); + } + + // + result = zone.IsValid(); + + // + // Forward Zone to Break By Shadow ... + if (result) + { + // + XOHCL tmpBar; + int idx = zone.FromIndex() - 1; + bool canContinue = true; + while (canContinue) + { + // + idx++; + tmpBar.Clean(); + canContinue = bar.BarAt(idx, tmpBar); + if (!canContinue) + { + break; + } + + // + canContinue = + isBullish + ? tmpBar.low > zone.lower + : tmpBar.high < zone.upper; + if (!canContinue) + { + break; + } + + // + zone.from = tmpBar.time; + } + + // + // Detect Liquidity Zone ... + if (zone.IsValid() && tmpBar.IsValid()) + { + // + liquidity = zone; + + // + if (isBullish) + { + // + liquidity.upper = zone.lower; + liquidity.lower = tmpBar.low; + } + else if (isBearish) + { + // + liquidity.lower = zone.upper; + liquidity.upper = tmpBar.high; + } + + // + liquidity.type = "XLiquidoty"; + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Validate By Liquidity Zone ... + if (result && validateHasLiquidity) + { + // + result = result && + liquidity.IsValid(); + + // + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Validate By XFIMA Rejections ... + if (result && validateByXFIMARejected) + { + // + XOHCL rejectedBar; + if (isPBarIsPinBar) + { + rejectedBar = pBar; + } + else if (isPBarSignalKeyBar) + { + rejectedBar = p2Bar; + } + + // + result = rejectedBar.IsValid(); + if (result) + { + // + ENUM_X_DIRECTION forDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + int count = poiDetector.IsRejectXFIMA( + rejectedBar, + rejecteds, + forDir // + ); + result = IsValidSize(count); + } + + // + rejectedBar.Clean(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Validate Rejection by Cycleas MA Trending ... + if (result && validateByCyclesMATresnding) + { + // + int barIDX = pBar.Index(); + + // + bool isCyclesMABulliah = + fimaParser.IsHCMABullish(barIDX) && + fimaParser.IsHCMAOverLast(barIDX); + + // + bool isCyclesMABearish = + fimaParser.IsHCMABearish(barIDX) && + fimaParser.IsHCMAUnderLast(barIDX); + + // + isBullish = + isBullish && + isCyclesMABulliah; + + // + isBearish = + isBearish && + isCyclesMABearish; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Has a Zone (FVG, Support, Resistance) ... + if (result && validateByZones) + { + // + int bullishCount = 0; + int bearishCount = 0; + XBoxZone bullishZones[]; + XBoxZone bearishZones[]; + + // + // Detect Zones ... + int zonesCount = poiDetector.DetectZones( + bar, + zones, + true, // Validated Zones ... + false, // Contains Order Block ... + true, // Contains Fair Value Gaps ... + true, // Contains Supports ... + true, // Contains Resistances ... + 50, // Loopback ... + X_DIRECTION_ALL, // For All Directions ... + X_SORT_BY_DATE, // Sort by Date ... + X_DIRECTION_BEARISH, // Sorting Direction ... + 10, // Zones Validation Points Factor ... + 5, // Zones Loopback ... + 3, // Zones Validation ... + 0 // All Zones ... + ); + UpdateToTime(zones, bar.time); + + // + // Validate by Zones Existance ... + result = result && IsValidSize(zonesCount); + + // + // Validate By Direction Zones Existance ... + if (result) + { + // + // Separate Bullish Zones ... + bullishCount = ExtractByDirection( + bullishZones, + zones, + X_DIRECTION_BULLISH // + ); + + // + // Separate Bearish Zones ... + bearishCount = ExtractByDirection( + bearishZones, + zones, + X_DIRECTION_BEARISH // + ); + + // + // Select Directional Zone ... + int idx = -1; + if (isBullish && IsValidSize(bullishCount)) + { + idx = GetYoungest(bullishZones); + } + else if (isBearish && IsValidSize(bearishCount)) + { + idx = GetYoungest(bearishZones); + } + if (IsValidIndex(idx)) + { + if (isBullish) + { + directionalZone = bullishZones[idx]; + } + else if (isBearish) + { + directionalZone = bearishZones[idx]; + } + } + + // + // Select Indirectional Zone ... + idx = -1; + if (isBullish && IsValidSize(bearishCount)) + { + idx = GetYoungest(bearishZones); + } + else if (isBearish && IsValidSize(bullishCount)) + { + idx = GetYoungest(bullishZones); + } + if (IsValidIndex(idx)) + { + if (isBullish) + { + inDirectionalZone = bearishZones[idx]; + } + else if (isBearish) + { + inDirectionalZone = bullishZones[idx]; + } + } + + // + // Validate by Has Directional Zones ... + if (result && validateByHasDirectionalZones) + { + result = result && directionalZone.IsValid(); + } + + // + // Validate by Has InDirectional Zones ... + if (result && validateByHasInDirectionalZones) + { + result = result && inDirectionalZone.IsValid(); + } + } + + // + // Validate Directional and In Directional Zones Distance ... + if (result && validateByInDirectionalZonesPlacement) + { + // + double points = GetPoints(bar.symbol); + double slAddition = + slAdditionDistance > 0 + ? slAdditionDistance * points + : 0; + double spread = GetSpread(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double sl = isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + double risk = MathAbs(entry - sl); + double reward = risk * defaultSignalR2R; + double tp = isBullish + ? entry + reward + : entry - reward; + + // + if (inDirectionalZone.IsValid()) + { + // + isBullish = + isBullish && + tp < inDirectionalZone.lower && + entry < inDirectionalZone.lower; + + // + isBearish = + isBearish && + tp > inDirectionalZone.upper && + entry > inDirectionalZone.upper; + + // + result = isBullish || isBearish; + } + } + + // + // Cleanup ... + XClean(bullishZones); + XClean(bearishZones); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + dir = X_DIRECTION_NONE; + } + } + + // + // Validate Detected Zone By Crossed MA Fast Slow ... + if (result && validateByXFIMAMACrossed) + { + // + bool isBarHasBullishCross = fimaParser.IsMAFastCrossedOverLast(bar.Index()) && + fimaParser.IsMAFastCrossedOverSlow(bar.Index()); + bool isPBarHasBullishCross = fimaParser.IsMAFastCrossedOverLast(pBar.Index()) && + fimaParser.IsMAFastCrossedOverSlow(pBar.Index()); + bool isP2BarHasBullishCross = fimaParser.IsMAFastCrossedOverLast(p2Bar.Index()) && + fimaParser.IsMAFastCrossedOverSlow(p2Bar.Index()); + bool isP3BarHasBullishCross = fimaParser.IsMAFastCrossedOverLast(p3Bar.Index()) && + fimaParser.IsMAFastCrossedOverSlow(p3Bar.Index()); + bool hasBullishCross = isBarHasBullishCross || + isPBarHasBullishCross || + isP2BarHasBullishCross || + isP3BarHasBullishCross; + + // + bool isBarHasBearishCross = fimaParser.IsMAFastCrossedUnderLast(bar.Index()) && + fimaParser.IsMAFastCrossedUnderSlow(bar.Index()); + bool isPBarHasBearishCross = fimaParser.IsMAFastCrossedUnderLast(pBar.Index()) && + fimaParser.IsMAFastCrossedUnderSlow(pBar.Index()); + bool isP2BarHasBearishCross = fimaParser.IsMAFastCrossedUnderLast(p2Bar.Index()) && + fimaParser.IsMAFastCrossedUnderSlow(p2Bar.Index()); + bool isP3BarHasBearishCross = fimaParser.IsMAFastCrossedUnderLast(p3Bar.Index()) && + fimaParser.IsMAFastCrossedUnderSlow(p3Bar.Index()); + bool hasBearishCross = isBarHasBearishCross || + isPBarHasBearishCross || + isP2BarHasBearishCross || + isP3BarHasBearishCross; + + // + isBullish = + isBullish && + hasBullishCross; + + // + isBearish = + isBearish && + hasBearishCross; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // TODO: Remove this and Put inside Draws Part ... + if (result) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + XPatternAnalysisDrawConfig iPatternsConfig = structureDrawConfig.barAnalysisDrawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + // Draw Rejected Lines ... + if (HasChild(rejecteds)) + { + // + XTrend tmpTrend; + bool has = false; + int count = ArraySize(rejecteds); + for (int i = 0; i < count; i++) + { + // + tmpTrend.Clean(); + has = tmpTrend.Init( + bar.symbol, + bar.period, + bar.time, + rejecteds[i], + p2Bar.BeforeOn(), + rejecteds[i], + bar.time // + ); + + // + if (has) + { + poiDrawer.DrawTrendLine(tmpTrend, iConfig); + } + } + + // + tmpTrend.Clean(); + } + + // + // Draw Detected Zones ... + if (HasChild(zones)) + { + poiDrawer.DrawZones(zones, iConfig); + } + + // + // Draw Crossed Trends ... + if (validateByXFIMAMACrossed) + { + // + XTrend fastTrend; + XTrend slowTrend; + bool has = fastTrend.Init( + p2Bar.symbol, + p2Bar.period, + bar.time, + fimaHelper.GetMAFast(p2Bar.Index()), + p2Bar.time, + fimaHelper.GetMAFast(bar.Index()), + bar.time // + ); + if (has) + { + poiDrawer.DrawTrendLine(fastTrend, iConfig); + } + has = slowTrend.Init( + p2Bar.symbol, + p2Bar.period, + bar.time, + fimaHelper.GetMASlow(p2Bar.Index()), + p2Bar.time, + fimaHelper.GetMASlow(bar.Index()), + bar.time // + ); + if (has) + { + poiDrawer.DrawTrendLine(slowTrend, iConfig); + } + fastTrend.Clean(); + slowTrend.Clean(); + } + + // + // Draw Liquidity Zone ... + if (liquidity.IsValid()) + { + // + iConfig.bullishColor = clrGreen; + iConfig.bearishColor = clrRed; + poiDrawer.DrawZone(liquidity, iConfig); + iConfig.bullishColor = structureDrawConfig.drawConfig.bullishColor; + iConfig.bearishColor = structureDrawConfig.drawConfig.bearishColor; + } + + // + // Specified Zones ... + XPOIDrawConfig iSConfig = iConfig; + iSConfig.zonesWidth = 2; + iSConfig.bullishColor = clrYellow; + iSConfig.zonesStyle = STYLE_DASHDOTDOT; + iSConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (zone.IsValid()) + { + // + // iSConfig.zonesStyle = STYLE_SOLID; + // poiDrawer.DrawZone(zone, iSConfig); + // iSConfig.zonesStyle = STYLE_DASHDOTDOT; + } + + // + // Draw Directional Zone ... + if (directionalZone.IsValid()) + { + poiDrawer.DrawZone(directionalZone, iSConfig); + } + + // + // Draw InDirectional Zone ... + if (inDirectionalZone.IsValid()) + { + poiDrawer.DrawZone(inDirectionalZone, iSConfig); + } + + // + iConfig.Clean(); + iSConfig.Clean(); + } + + // + if (result) + { + // + DebugBreak(); + + // + // result = false; + // isBullish = false; + // isBearish = false; + } + + // + // Detecting Direction ... + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + // Since Zone Prepared in Above Steps ... + // here we only Validate it ... + result = zone.IsValid(); + + // + // Replace Zones SL Edge based on Sweeped Liquidity ... + if (liquidity.IsValid()) + { + // + if (isBullish) + { + zone.lower = liquidity.lower; + } + else if (isBearish) + { + zone.upper = liquidity.upper; + } + } + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(zones); + XClean(rejecteds); + liquidity.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + p3BarPatterns.Clean(); + iPatternsConfig.Clean(); + directionalZone.Clean(); + inDirectionalZone.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * Strategy 2: + * =========== + * - Works Based On PBar Patterns Focused on PinBar ... + * - Looking for a Bar Directional Pattern Happens ... + * - Validate Fast Ma Over/Under Slow ... + * - Validate P2Peak/Vale doesnt Under or Over Last (InDirectional) ... + * - Validate P2Bar Has Directional Market Strucuture Zone (OB, FVG, Support/Resistance) ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarPatterns; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + structureConfig.barsAnalysisConfig // + ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Check Boundary Trend ... + XTrend boundaryTrend; + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // Check Bar Patterns ... + + // + // Bars Sequences ... + bool hasBullishSequence = p3Bar.IsBearish() && + pBar.IsBullish(); + bool hasBearishSequence = p3Bar.IsBullish() && + pBar.IsBearish(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Check Based On LC and HC MA State ... + + // + bool isLCMABullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCMABullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isCycleMABullish = isLCMABullish && isHCMABullish; + + // + bool isLCMABearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCMABearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isCycleMABearish = isLCMABearish && isHCMABearish; + + // + // Do ... + + // + isBullish = + // + hasSupport && + isFastOverLast && + isValeUnderLast && + isCycleMABullish && + hasBullishSequence && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + hasBoundaryBullishTrend && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + hasResistance && + isPeakOverLast && + isFastUnderLast && + isCycleMABearish && + !isP2ValeOverLast && + hasBearishSequence && + isPBarCloseUnderFast && + isP2BarBearishPinned && + hasBoundaryBearishTrend && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Draws ... + if (result) + { + // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine(boundaryTrend, iConfig); + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // iConfig.Clean(); + + // + // DebugBreak(); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Strategy 3: + * =========== + * - Works Based On Breaked Support or Resistances ... + * - Looking for a Support or Resistance to Breaked ... + * - Validate Breaker Bar to Change Peak or Vale ... + * - Validate Bar Opposit Side of Breaker Bar's Shadow ... + * - Validate by Checking Market Strucutre to Has Directional Zone + * (Support for Resistance Break / Resistance for Support Break) ... + * - Validate Breaker Bar to Has Directional FVG ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + + // + bool validateByPVChanges = true; + bool validateByGapExists = true; + bool validateByBarShadows = true; + bool validateHasDirectionalZone = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XBoxZone _fvg; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + // Price Must Break Support or Resistance ... + + // + // Extract Support and Resistance ... + bool hasSupport = p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsResistance(); + if (hasSupport) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, _support); + tmpBar.Clean(); + tmpPivot.Clean(); + } + if (hasResistance) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + tmpBar.Clean(); + tmpPivot.Clean(); + } + + // + bool hasBreakedSupport = hasSupport && + pBar.close < _support.lower && + p2Bar.close > _support.lower; + bool hasBreakedResistance = hasResistance && + pBar.close > _resistance.upper && + p2Bar.close < _resistance.upper; + + // + isBullish = hasBreakedResistance; + isBearish = hasBreakedSupport; + + // + result = isBullish || isBearish; + + // + // Validate By PV Changed ... + // Breaker Bar must Change Peak or Value ... + if (result && validateByPVChanges) + { + // + bool isPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + + // + isBullish = + isBullish && + isPeakOverLast; + + // + isBearish = + isBearish && + isValeUnderLast; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Bar Shadows ... + // Breakre Bar Side Shadow must not Reached ... + if (result && validateByBarShadows) + { + // + isBullish = + isBullish && + pBar.low > p2Bar.low; + + // + isBearish = + isBearish && + pBar.high < p2Bar.high; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Has Directional Zone ... + if (result && validateHasDirectionalZone) + { + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate By Gap Exists ... + if (result && validateByGapExists) + { + // + ENUM_X_DIRECTION tmpDir; + bool hasFVG = poiDetector.HasFVG( + pBar, + tmpDir, + _fvg // + ); + + // + isBullish = + isBullish && + hasFVG && + IsXBullish(tmpDir); + + // + isBearish = + isBearish && + hasFVG && + IsXBearish(tmpDir); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Prepare Direction and Zone ... + if (result) + { + // + if (isBullish) + { + // + zone = _resistance; + zone.dir = Opposit(_resistance.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + if (isBearish) + { + // + zone = _support; + zone.dir = Opposit(_support.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + // Zone Validation Base ... + result = zone.IsValid(); + if (result) + { + // + // Validate By Trend of Zone ... + XTrend zoneTrend; + XTrend zoneToTrend; + + // + // Detecting Trends ... + result = poiDetector.HasBoundaryTrend(zone, zoneTrend, false); + result = result && + poiDetector.HasBoundaryTrend(zone, zoneToTrend, true); + + // + // Validate Trend ... + result = + result && + zone.dir == zoneTrend.dir && + zone.dir == zoneToTrend.dir; + + // + // Draw ... + if (result) + { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + + // // + // poiDrawer.DrawTrendLine(zoneTrend, iConfig); + // poiDrawer.DrawTrendLine(zoneToTrend, iConfig); + + // // + // iConfig.Clean(); + } + + // + // Cleanup ... + zoneTrend.Clean(); + zoneToTrend.Clean(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + result = zone.IsValid(); + } + + // + if (result) + { + // + if (_support.IsValid()) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (_resistance.IsValid()) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (pBarPatterns.IsValid()) + { + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + patternConfig.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Strategy 4: + * =========== + * - Works Based on Order Flow ... + * - Looking for new and Fresh Order Flow ... + * - Validate Bar is Inside Order Flow ... + * - Validate Bar has Proper Pattern ... + * - Validate Bar Based on ATR Band in two Step: + * - Step 1: Bars is Inside ATR Band (Middle) ... + * - Step 2: Trigger Bars Close Price based on ATR Band ... + * - Validate Order Flow based on Market Structure Zone ... + * - Validate Trigger Bar based on InDirectional Market Structure Zones ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateBarInsideZone = true; + bool validateByBarPatterns = true; + bool validateByXFIMABoundary = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = true; + bool validateMarketStructureHasDirectionalZone = true; + bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; + bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + // Detecting OrderFlow ... + XBoxZone oFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + p3Bar, + dir, + oFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + + // + XTrend boundaryTrend; + XTrend boundaryZoneTrend; + + // + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + double atrBandMiddle = EMPTY_VALUE; + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force Price of p2Bar is Inside Order Flow ... + if (result && validateBarInsideZone) + { + // + double orderFlowUpper = 0; + double orderFlowLower = 0; + + // + int idx = -1; + idx = GetHighest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowUpper = oFlow[idx].upper; + } + idx = GetLowest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowLower = oFlow[idx].lower; + } + + // + result = NotEmptyZero(orderFlowUpper) && + NotEmptyZero(orderFlowLower) && + orderFlowUpper > orderFlowLower && + (isBullish + ? p2Bar.low < orderFlowUpper + : p2Bar.high > orderFlowLower); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + // (bar.close > pBar.low || + // bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + // (bar.close < pBar.high || + // bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force P2Bar Place Checking based on ATR Band ... + if (result && validateByBarInsideATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); + + // + atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); + + // + isBullish = + isBullish && + NotEmptyZero(atrBandMiddle) && + p2Bar.low < atrBandMiddle; + + // + isBearish = + isBearish && + NotEmptyZero(atrBandMiddle) && + p2Bar.high > atrBandMiddle; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Place Checking based on ATR Band ... + if (result && validateByBarBasedOnATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); + + // + result = + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower) && + (isBullish + ? pBar.close > atrBandLower + : pBar.close < atrBandUpper); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // for Bullish has Support ... + // for Bearish has Resistance ... + if (result && validateMarketStructureHasDirectionalZone) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Validate Support and Resistance by Order Flow ... + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + // Check Market Strucutre Support and Resistance Validation ... + if (validateMarketStructureDirectionalZoneInsideOrderFlow) + { + // + hasSupport = + hasOFBox && + hasSupport && + ofZone.lower < _support.lower && + ofZone.upper > _support.upper; + + // + hasResistance = + hasOFBox && + hasResistance && + ofZone.lower < _resistance.lower && + ofZone.upper > _resistance.upper; + } + + // + // Validate Directional Support or Resistance Exists ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Makret Structure Has Not Indirectional Zone ... + if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + bool hasIndirectionalZone = + (isBullish && hasResistance) || + (isBearish && hasSupport); + if (hasIndirectionalZone) + { + // + // Here we Have to Validate Zone Place ... + + // + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Bullish ... + if (isBullish && hasResistance) + { + hasResistance = _resistance.lower <= tp; + } + + // + // Bearish ... + if (isBearish && hasSupport) + { + hasSupport = _support.upper >= tp; + } + } + + // + isBullish = + isBullish && + !hasResistance; + + // + isBearish = + isBearish && + !hasSupport; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate ... + result = isBullish || isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone and do Zone Based Validations ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Refine Zone ... + zone.to = bar.time; + zone.upper = MathMax(zone.upper, atrBandMiddle); + zone.lower = MathMin(zone.lower, atrBandMiddle); + + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Try to Retrieve Boundary To Trend ... + result = poiDetector.HasBoundaryTrend( + zone, + boundaryTrend, + true // + ); + + // + // Try to Retrieve Boundary Zone Trend ... + result = + result && + poiDetector.HasBoundaryTrend( + zone, + boundaryZoneTrend, + false // + ); + + // + // Check and Validate Trend Direction ... + result = + result && + zone.dir == boundaryTrend.dir && + zone.dir == boundaryZoneTrend.dir; + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + } + } + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + XTarget iTarget; + + // + // Calculate Requirements ... + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // High Risk Target is Used to Protect In Profit Positiions + // from Reversal Patterns ... + double highRiskR2r = (defaultSignalR2R / 5) * 4; + double highRiskReward = highRiskR2r * risk; + double highRiskTP = isBullish + ? entry + highRiskReward + : entry - highRiskReward; + iTarget.Clean(); + iTarget.actingDistance = 5; + iTarget.doRFOnEntry = true; + iTarget.target = highRiskTP; + iTarget.volumeMultiplier = 0.8; + // AddRef(iTarget, targets); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(oFlow); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); + boundaryZoneTrend.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 new file mode 100644 index 0000000..c0dd4f9 --- /dev/null +++ b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -0,0 +1,2231 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAPoiDetector ... +// Description: XFIMA POI Detector 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 XFIMA POI Detector Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.xfima.lib.mq5" + +// +// Definitions ... + +enum ENUM_XFIMA_PIVOTS +{ + XFIMA_PIVOT_NONE = 0, + XFIMA_PIVOT_PV = 1, + XFIMA_PIVOT_ATR = 2, + XFIMA_PIVOT_ZIGZAG = 3, + XFIMA_PIVOT_MA_CROSS = 4, + XFIMA_PIVOT_HK_SWITCH = 5, + XFIMA_PIVOT_SAR_SWITCH = 6, + XFIMA_PIVOT_BOUNDARY_SWITCH = 7, +}; + +bool IsXValid(ENUM_XFIMA_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XFIMA_PIVOT_NONE; + + // + return result; +} + +string ToXString(ENUM_XFIMA_PIVOTS value) +{ + // + string result = NULL; + + // + if (!IsXValid(value)) + { + return result; + } + + // + switch (value) + { + // + case XFIMA_PIVOT_NONE: + result = "NONE"; + break; + + // + case XFIMA_PIVOT_PV: + result = "XPV"; + break; + + // + case XFIMA_PIVOT_ATR: + result = "XATR"; + break; + + // + case XFIMA_PIVOT_ZIGZAG: + result = "XZGP"; + break; + + // + case XFIMA_PIVOT_MA_CROSS: + result = "XMACRS"; + break; + + // + case XFIMA_PIVOT_HK_SWITCH: + result = "XHKSWCH"; + break; + + // + case XFIMA_PIVOT_SAR_SWITCH: + result = "XSARSWCH"; + break; + + // + case XFIMA_PIVOT_BOUNDARY_SWITCH: + result = "XBNDSWCH"; + break; + } + + // + return result; +} + +ENUM_XFIMA_PIVOTS ToXFIMAPivots(string value) +{ + // + ENUM_XFIMA_PIVOTS result = XFIMA_PIVOT_NONE; + + // + if (!IsXValid(value)) + { + return result; + } + + // + if (value == ToXString(XFIMA_PIVOT_NONE)) + { + result = XFIMA_PIVOT_NONE; + } + else if (value == ToXString(XFIMA_PIVOT_PV)) + { + result = XFIMA_PIVOT_PV; + } + else if (value == ToXString(XFIMA_PIVOT_ATR)) + { + result = XFIMA_PIVOT_ATR; + } + else if (value == ToXString(XFIMA_PIVOT_ZIGZAG)) + { + result = XFIMA_PIVOT_ZIGZAG; + } + else if (value == ToXString(XFIMA_PIVOT_MA_CROSS)) + { + result = XFIMA_PIVOT_MA_CROSS; + } + else if (value == ToXString(XFIMA_PIVOT_HK_SWITCH)) + { + result = XFIMA_PIVOT_HK_SWITCH; + } + else if (value == ToXString(XFIMA_PIVOT_SAR_SWITCH)) + { + result = XFIMA_PIVOT_SAR_SWITCH; + } + else if (value == ToXString(XFIMA_PIVOT_BOUNDARY_SWITCH)) + { + result = XFIMA_PIVOT_BOUNDARY_SWITCH; + } + + // + return result; +} + +// +// Implementation ... +class XCXFIMAPOIDetector : public XCMarketPatternDetector +{ + // + // Public ... + public: + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCXFIMAHelper *fimaHelper; // XFIMA Helper ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + + // + // Constructor ... + XCXFIMAPOIDetector( + XCXFIMAHelper *_fimaHelper, + XCXFIMAHelperParser *_fimaParser // + ) : XCMarketPatternDetector() + { + // + barAnalyser = new XCBarAnalyser(); + fimaHelper = _fimaHelper; + fimaParser = _fimaParser; + + // + symbol = fimaHelper.GetSymbol(); + period = fimaHelper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCXFIMAPOIDetector() + { + Destroy(); + } + + // + // Actions and Tools ... + + // + // Detectors ... + + // + // XPV ... + + /** + * Check Conditions to Detecte XPV based Consolidation Zone ... + * + * @param zone: XBoxZone, reference to holds detected zone ... + * @param barIndex: int, Specified Bar Index ... + * @param forcePVBreak: bool, force to has PV Side Break ... + * @param forceHasSarSwitch: bool, force to has SAR Switche ... + * + * @return ( bool ) + */ + bool DetectPVConsolidationZone( + XBoxZone &zone, + int barIndex = 0, + bool forcePVBreak = false, + bool forceHasSarSwitch = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + result = fimaParser.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool isPeakSame = fimaParser.IsPeakSame(barIndex); + bool isValeSame = fimaParser.IsValeSame(barIndex); + result = !(isPeakSame && + isValeSame); + if (!result) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double iVale = EMPTY_VALUE; + + // + int idx = barIndex; + bool canLookup = true; + while (canLookup) + { + // + idx++; + isPeakSame = fimaParser.IsPeakSame(idx); + isValeSame = fimaParser.IsValeSame(idx); + result = isPeakSame && + isValeSame; + if (!result) + { + // + zone.from = GetBarTime(symbol, period, idx); + break; + } + + // + if (idx == barIndex + 1) + { + // + zone.to = GetBarTime( + symbol, + period, + idx // + ); + } + + // + zone.from = GetBarTime( + symbol, + period, + idx // + ); + + // + iPeak = fimaHelper.GetPeak(idx); + iVale = fimaHelper.GetVale(idx); + + // + zone.lower = + !NotEmptyZero(zone.lower) + ? iVale + : MathMin(zone.lower, iVale); + + // + zone.upper = + !NotEmptyZero(zone.upper) + ? iPeak + : MathMax(zone.upper, iPeak); + } + + // + // Validating Zone Params ... + result = + // + IsXValid(zone.to) && + IsXValid(zone.from) && + zone.from < zone.to && + // + NotEmptyZero(zone.lower) && + NotEmptyZero(zone.upper) && + zone.upper > zone.lower + // + ; + + // + // Prepare Zone ... + if (result) + { + // + iPeak = fimaHelper.GetPeak(barIndex); + iVale = fimaHelper.GetVale(barIndex); + bool isPeakOverLast = fimaParser.IsPeakOverLast(barIndex); + bool isValeUnderLast = fimaParser.IsValeUnderLast(barIndex); + bool isValeBreak = iVale < zone.lower; + bool isPeakBreak = iPeak > zone.upper; + bool isPVBreak = isPeakBreak || + isValeBreak; + + // + zone.at = GetBarTime(symbol, period, barIndex); + zone.symbol = symbol; + zone.period = period; + zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) + ? X_DIRECTION_BULLISH + : (isValeUnderLast && !isPeakOverLast && isPVBreak) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Refine Zone Upper and Lower ... + if (zone.IsValid()) + { + // + XOHCL iBar; + int zoneLoopback = zone.FromIndex() - zone.ToIndex(); + result = zone.ToBar(iBar) && + IsValidSize(zoneLoopback); + if (result) + { + // + double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); + double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); + result = NotEmptyZero(zoneLL) && + NotEmptyZero(zoneHH); + if (result) + { + // + zone.lower = zone.lower == zoneLL + ? zone.lower + : MathMax(zone.lower, zoneLL); + + // + zone.upper = zone.upper == zoneHH + ? zone.upper + : MathMin(zone.upper, zoneHH); + } + } + + // + iBar.Clean(); + } + + // + // Validate ... + result = zone.IsValid(); + } + + // + // Validate Zones From ... + if (result) + { + // + int idx = zone.FromIndex(); + + // + iPeak = fimaHelper.GetPeak(idx); + iVale = fimaHelper.GetVale(idx); + + // + bool isValeOverLast = fimaParser.IsValeOverLast(idx); + bool isPeakUnderLast = fimaParser.IsPeakUnderLast(idx); + + // + result = + result && + (zone.IsBullish() + ? !isPeakUnderLast + : zone.IsBearish() + ? !isValeOverLast + : false); + } + + // + // Apply Forces ... + + // + // PV Break ... + // Peak or Vale must Breaked at Bar ... + if (result && forcePVBreak) + { + // + bool isPVBreaked = + (zone.IsBullish() && fimaParser.IsPeakOverLast(barIndex)) || + (zone.IsBearish() && fimaParser.IsValeUnderLast(barIndex)); + + // + result = result && + isPVBreaked; + } + + // + // Other Loop based Forces ... + if (result && (forceHasSarSwitch)) + { + + // + bool hasSarSwitch = false; + + // + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + // Check Sar Switches ... + if (forceHasSarSwitch && !hasSarSwitch) + { + // + hasSarSwitch = + zone.IsBullish() + ? fimaParser.IsSARSwitchedToBullish(i) + : fimaParser.IsSARSwitchedToBearish(i); + } + } + + // + // Validate Forces ... + if (forceHasSarSwitch) + { + // + result = + result && + hasSarSwitch; + } + } + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Detect XPV Zone ... + * + * @param zone: XBoxZone, reference to Holds detected Zone ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool DetectXPVZone( + XBoxZone &zone, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + result = fimaParser.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(fimaParser.symbol, fimaParser.period, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Vale ... + bool isValeOverLast = fimaParser.IsValeOverLast(barIndex); + bool isValeUnderLast = fimaParser.IsValeUnderLast(barIndex); + bool isNewVale = isValeOverLast || isValeUnderLast; + + // + // Peak ... + bool isPeakOverLast = fimaParser.IsPeakOverLast(barIndex); + bool isPeakUnderLast = fimaParser.IsPeakUnderLast(barIndex); + bool isNewPeak = isPeakOverLast || isPeakUnderLast; + + // + // Detect new Peak or Vale ... + result = isNewVale || isNewPeak; + + // + // Count Same Peaks and Same Vales from Index of Prev ... + int pIDX = barIndex + 1; + int samePeaks = fimaParser.CountSamePeaks(pIDX); + int sameVales = fimaParser.CountSameVales(pIDX); + result = + result && + IsValidSize(samePeaks) && + IsValidSize(sameVales); + + // + // Try to Evaluate Zone ... + int peaksStartIndex = pIDX + samePeaks; + int valesStartIndex = pIDX + sameVales; + int fromIDX = MathMin(peaksStartIndex, valesStartIndex); + if (result) + { + // + // Assign Zone Symbol / Period ... + zone.symbol = fimaParser.symbol; + zone.period = fimaParser.period; + + // + // Calculate Zone Times ... + zone.to = GetBarTime( + zone.symbol, + zone.period, + barIndex // + ); + zone.from = GetBarTime( + zone.symbol, + zone.period, + fromIDX // + ); + zone.at = zone.to; + + // + // Calculate Upper and Lower ... + zone.upper = fimaHelper.GetPeak(fromIDX); + zone.lower = fimaHelper.GetVale(fromIDX); + + // + // Validate Zone Upper and Lower ... + for (int i = pIDX; i <= fromIDX; i++) + { + // + if (isValeUnderLast) + { + zone.lower = MathMin(zone.lower, fimaHelper.GetVale(i)); + } + + // + if (isPeakOverLast) + { + zone.upper = MathMax(zone.upper, fimaHelper.GetPeak(i)); + } + } + + // + // Calculate Zone Direction ... + zone.dir = + isValeOverLast + ? X_DIRECTION_BULLISH + : isValeUnderLast + ? X_DIRECTION_BEARISH + : isPeakOverLast + ? X_DIRECTION_BULLISH + : isPeakUnderLast + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + // Refine Zone Upper / Lower based on Direction and Bars ... + + // + // Detect Highest High / Lowest Low ... + double ll = bar.FindLowest(fromIDX - barIndex, MODE_LOW); + double hh = bar.FindHighest(fromIDX - barIndex, MODE_HIGH); + + // + if (isNewVale) + { + zone.upper = MathMin(zone.upper, hh); + } + + // + if (isNewPeak) + { + zone.lower = MathMax(zone.lower, ll); + } + + // + // Set Zone Type ... + zone.type = ToXString(XFIMA_PIVOT_PV); + + // + // Summarize result ... + result = zone.IsValid(); + } + + // + result = zone.IsValid(); + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + bar.Clean(); + + // + return result; + } + + // + // Analysors ... + + /** + * Analyse Market ... + * + * @param structure: XFIMAMarketStructure, reference to holds Market Strucutre ... + * @param config: XFIMAMarketStructureConfig, reference to Provide Structure Analyse Config ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool AnalyseMarket( + XFIMAMarketStructure &structure, + XFIMAMarketStructureConfig &config, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + structure.Clean(); + + // + // Normalize ... + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + result = fimaParser.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + int idx = -1; + XOHCL tmpBar; + datetime fromTime = NULL; + XPatternAnalysis tmpBarAnalysis; + + // + // Initialize Indexed Bar ... + result = structure.bar.Init(symbol, period, barIndex); + + // + // Analyse Bar Patterns ... + if (result) + { + // + result = AnalyseBarPatterns( + structure.bar, + structure.barAnalysis, + config.barsAnalysisConfig // + ); + } + + // + // Analyse Pivots ... + + // + // XPV ... + CollectPVPivots( + structure.pvPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XMA ... + CollectMAPivots( + structure.maPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XZG ... + CollectZGPivots( + structure.zgPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XHK ... + CollectHKPivots( + structure.hkPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XSAR ... + CollectSARPivots( + structure.sarPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XPV Analysis ... + if (result && config.analysePVPivots) + { + // + result = HasChild(structure.pvPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.pvPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.pvPivots[idx].time + : MathMin(fromTime, structure.pvPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.pvAnalysis.Init( + ToXString(XFIMA_PIVOT_PV), + symbol, + period, + structure.pvPivots // + ); + } + } + + // + // XZG Analysis ... + if (result && config.analyseZGPivots) + { + // + result = HasChild(structure.zgPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.zgPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.zgPivots[idx].time + : MathMin(fromTime, structure.zgPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.zgAnalysis.Init( + ToXString(XFIMA_PIVOT_ZIGZAG), + symbol, + period, + structure.zgPivots // + ); + } + } + + // + // XHK Analysis ... + if (result && config.analyseHKPivots) + { + // + result = HasChild(structure.hkPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.hkPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.hkPivots[idx].time + : MathMin(fromTime, structure.hkPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.hkAnalysis.Init( + ToXString(XFIMA_PIVOT_HK_SWITCH), + symbol, + period, + structure.hkPivots // + ); + } + } + + // + // XMA Analysis ... + if (result && config.analyseMAPivots) + { + result = HasChild(structure.maPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.maPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.maPivots[idx].time + : MathMin(fromTime, structure.maPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.maAnalysis.Init( + ToXString(XFIMA_PIVOT_MA_CROSS), + symbol, + period, + structure.maPivots // + ); + } + } + + // + // XSAR Analysis ... + if (result && config.analyseSARPivots) + { + // + result = HasChild(structure.sarPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.sarPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.sarPivots[idx].time + : MathMin(fromTime, structure.sarPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.sarAnalysis.Init( + ToXString(XFIMA_PIVOT_SAR_SWITCH), + symbol, + period, + structure.sarPivots // + ); + } + } + + // + // Order Flow ... + if (result && config.detectOrderFlow) + { + // + HasOrderFlow( + structure.bar, + structure.orderFlowDir, + structure.orderFlow, + config.orderFlowValidation, + config.orderFlowUseOB, + config.orderFlowUseFVG, + config.orderFlowUseSupportAndResistance, + config.barsAnalysisConfig.supportAndResistanceLoopbackLength, + config.barsAnalysisConfig.supportAndResistanceValidationLength, + config.loopback // + ); + } + + // + // Analyse Bar Patterns ... + if (result && config.analyseBarPatterns) + { + // + // Collect Pivots ... + XPivot tmps[]; + Copy(structure.pvPivots, tmps, false); + Copy(structure.zgPivots, tmps, false); + Copy(structure.hkPivots, tmps, false); + Copy(structure.maPivots, tmps, false); + Copy(structure.sarPivots, tmps, false); + + // + XPivot sames[]; + XPivot tmpPivot; + int samesCount = 0; + while (HasChild(tmps)) + { + // + tmpPivot.Clean(); + tmpPivot = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + XClean(sames); + samesCount = ExtractSameTimePivots(tmpPivot, sames, tmps); + if (HasChild(sames)) + { + // + tmpBar.Clean(); + if (sames[0].GetBar(tmpBar)) + { + // + tmpBarAnalysis.Clean(); + if (AnalyseBarPatterns(tmpBar, tmpBarAnalysis, config.barsAnalysisConfig)) + { + // + AddRef(tmpBarAnalysis, structure.barsAnalysis); + } + } + + // + Removes(sames, tmps); + } + } + + // + // Bars Analysis Exists ... + result = HasChild(structure.barsAnalysis); + + // + // Cleanup ... + XClean(tmps); + XClean(sames); + tmpPivot.Clean(); + } + + // + // Cleanup ... + if (!result) + { + structure.Clean(); + } + + // + return result; + } + + // + // Collectors ... + + /** + * Collect ZigZag Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectZGPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsZGLow(i); + isBearish = fimaParser.IsZGHigh(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_ZIGZAG) // + ); + if (has) + { + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + /** + * Collect MA Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectMAPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsMAFastCrossedOverSlow(i); + isBearish = fimaParser.IsMAFastCrossedUnderSlow(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_MA_CROSS) // + ); + if (has) + { + // + // Replace MA Values ... + pivot.value = + isBullish + ? fimaHelper.GetMASlow(barIndex) + : fimaHelper.GetMAFast(barIndex); + + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + /** + * Collect HK Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectHKPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsHKSwitchedToBullish(i); + isBearish = fimaParser.IsHKSwitchedToBearish(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_HK_SWITCH) // + ); + if (has) + { + // + // Replace Value ... + pivot.value = + isBullish + ? fimaHelper.GetHKLow(i) + : fimaHelper.GetHKHigh(i); + + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + /** + * Collect PV Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectPVPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsPeakOverLast(i); + isBearish = fimaParser.IsValeUnderLast(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_PV) // + ); + if (has) + { + // + // Replace Value ... + pivot.value = + isBullish + ? fimaHelper.GetHKLow(i) + : fimaHelper.GetHKHigh(i); + + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + /** + * Collect SAR Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectSARPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsSARSwitchedToBullish(i); + isBearish = fimaParser.IsSARSwitchedToBearish(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_SAR_SWITCH) // + ); + if (has) + { + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + /** + * Collect Specified ZOnes Boundary Min / Max Values ... + * + * @param uppers: XPivot, collection reference to holds Peaks of Zone's Boundary ... + * @param lowers: XPivot, collection reference to holds Vales of Zone's Boundary ... + * @param zone: XBoxZone, reference to Provide Specified Zone for Boundary Detection ... + * + * @return ( int ) + */ + int CollectZonesBoundary( + XPivot &uppers[], + XPivot &lowers[], + XBoxZone &zone // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(uppers); + XClean(lowers); + + // + // Validate ... + bool has = zone.IsValid() && + fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + double iUpper; + double iLower; + datetime iTime; + XPivot upperPivot; + XPivot lowerPivot; + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + iUpper = fimaParser.GetBoundaryMax(i); + iLower = fimaParser.GetBoundaryMin(i); + iTime = GetBarTime(zone.symbol, zone.period, i); + + // + has = + IsXValid(iTime) && + NotEmptyZero(iUpper) && + NotEmptyZero(iLower); + if (has) + { + // + // Upper Pivot ... + upperPivot.Clean(); + has = upperPivot.Init( + iUpper, + iTime, + zone.symbol, + zone.dir, + zone.period, + X_PIVOT_TYPE_PEAK // + ); + if (has) + { + upperPivot.prefix = "XBNDUP"; + } + + // + // Lower Pivot ... + lowerPivot.Clean(); + has = lowerPivot.Init( + iLower, + iTime, + zone.symbol, + zone.dir, + zone.period, + X_PIVOT_TYPE_VALE // + ); + if (has) + { + lowerPivot.prefix = "XBNDLO"; + } + + // + has = upperPivot.IsValid() && + lowerPivot.IsValid(); + if (has) + { + // + AddRef(upperPivot, uppers); + AddRef(lowerPivot, lowers); + } + } + } + + // + result = MathMin(ArraySize(uppers), ArraySize(lowers)); + + // + // Cleanup ... + upperPivot.Clean(); + lowerPivot.Clean(); + + // + return result; + } + + /** + * Check Zone Has Boundary Trend or not ... + * + * @param zone: XBoxZOne, reference to Specified Zone for Checking Trend ... + * @param trend: XTrend, reference to holds Detected Trend Result ... + * @param basedOnToTime: bool, if set true, do based on to and it's prev bar ... + * + * @return ( bool ) + */ + bool HasBoundaryTrend( + XBoxZone &zone, + XTrend &trend, + bool basedOnToTime = false // + ) + { + // + bool result = false; + + // + // Prepare ... + trend.Clean(); + + // + // Validate ... + result = + zone.IsValid() && + fimaParser.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + int toIDX = zone.ToIndex(); + int fromIDX = + basedOnToTime + ? toIDX + 1 + : zone.FromIndex(); + datetime fromTime = GetBarTime(zone.symbol, zone.period, fromIDX); + + // + double toMin = fimaParser.GetBoundaryMin(toIDX); + double toMax = fimaParser.GetBoundaryMax(toIDX); + + // + double fromMin = fimaParser.GetBoundaryMin(fromIDX); + double fromMax = fimaParser.GetBoundaryMax(fromIDX); + + // + bool isMinBullish = fromMin < toMin; + bool isMaxBullish = fromMax < toMax; + bool isBullish = isMinBullish && isMaxBullish; + + // + bool isMinBearish = fromMin > toMin; + bool isMaxBearish = fromMax > toMax; + bool isBearish = isMinBearish && isMaxBearish; + + // + result = isBullish || isBearish; + if (result) + { + // + result = trend.Init( + zone.symbol, + zone.period, + TimeCurrent(), + isBullish + ? fromMin + : fromMax, + fromTime, + isBullish + ? toMin + : toMax, + zone.to // + ); + } + + // + // Validate Result ... + result = trend.IsValid() && + trend.HasTrend(); + if (!result) + { + trend.Clean(); + } + + // + return result; + } + + /** + * Get Cycle Based PV Zone ... + * + * @param bar: XOHCL, reference to Specified Zone ... + * @param zone: XBoxZone, reference to holds PV Zone ... + * + * @return ( bool ) + */ + bool GetSCZone( + XOHCL &bar, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index(); + + // + double upper = fimaHelper.GetSHH(barIndex); + double lower = fimaHelper.GetSLL(barIndex); + double pHH = fimaHelper.GetSHH(barIndex + 1); + double pLL = fimaHelper.GetSLL(barIndex + 1); + int sameLLs = fimaParser.CountSCSameLLs(barIndex); + int sameHHs = fimaParser.CountSCSameHHs(barIndex); + int fromIDX = barIndex + MathMax(sameLLs, sameHHs); + + // + zone.to = bar.time; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.dir = + (upper > pHH || + lower > pLL) + ? X_DIRECTION_BULLISH + : (upper < pHH || + lower < pLL) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(XFIMA_PIVOT_PV) + "_SC"; + zone.from = GetBarTime(bar.symbol, bar.period, fromIDX); + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Get Cycle Based PV Zone ... + * + * @param bar: XOHCL, reference to Specified Zone ... + * @param zone: XBoxZone, reference to holds PV Zone ... + * + * @return ( bool ) + */ + bool GetMCZone( + XOHCL &bar, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index(); + + // + double upper = fimaHelper.GetMHH(barIndex); + double lower = fimaHelper.GetMLL(barIndex); + double pHH = fimaHelper.GetMHH(barIndex + 1); + double pLL = fimaHelper.GetMLL(barIndex + 1); + int sameLLs = fimaParser.CountMCSameLLs(barIndex); + int sameHHs = fimaParser.CountMCSameHHs(barIndex); + int fromIDX = barIndex + MathMax(sameLLs, sameHHs); + + // + zone.to = bar.time; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.dir = + (upper > pHH || + lower > pLL) + ? X_DIRECTION_BULLISH + : (upper < pHH || + lower < pLL) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(XFIMA_PIVOT_PV) + "_MC"; + zone.from = GetBarTime(bar.symbol, bar.period, fromIDX); + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Get Cycle Based PV Zone ... + * + * @param bar: XOHCL, reference to Specified Zone ... + * @param zone: XBoxZone, reference to holds PV Zone ... + * + * @return ( bool ) + */ + bool GetLCZone( + XOHCL &bar, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index(); + + // + double upper = fimaHelper.GetLHH(barIndex); + double lower = fimaHelper.GetLLL(barIndex); + double pHH = fimaHelper.GetLHH(barIndex + 1); + double pLL = fimaHelper.GetLLL(barIndex + 1); + int sameLLs = fimaParser.CountLCSameLLs(barIndex); + int sameHHs = fimaParser.CountLCSameHHs(barIndex); + int fromIDX = barIndex + MathMax(sameLLs, sameHHs); + + // + zone.to = bar.time; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.dir = + (upper > pHH || + lower > pLL) + ? X_DIRECTION_BULLISH + : (upper < pHH || + lower < pLL) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(XFIMA_PIVOT_PV) + "_LC"; + zone.from = GetBarTime(bar.symbol, bar.period, fromIDX); + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Get Cycle Based PV Zone ... + * + * @param bar: XOHCL, reference to Specified Zone ... + * @param zone: XBoxZone, reference to holds PV Zone ... + * + * @return ( bool ) + */ + bool GetHCZone( + XOHCL &bar, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index(); + + // + double upper = fimaHelper.GetHHH(barIndex); + double lower = fimaHelper.GetHLL(barIndex); + double pHH = fimaHelper.GetHHH(barIndex + 1); + double pLL = fimaHelper.GetHLL(barIndex + 1); + int sameLLs = fimaParser.CountHCSameLLs(barIndex); + int sameHHs = fimaParser.CountHCSameHHs(barIndex); + int fromIDX = barIndex + MathMax(sameLLs, sameHHs); + + // + zone.to = bar.time; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.dir = + (upper > pHH || + lower > pLL) + ? X_DIRECTION_BULLISH + : (upper < pHH || + lower < pLL) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(XFIMA_PIVOT_PV) + "_HC"; + zone.from = GetBarTime(bar.symbol, bar.period, fromIDX); + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * Check Specified Bar is Rejected Specified XFIMA Values or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param rejecteds: double, collection reference to holds Rejected Values ... + * @param forDir: ENUM_X_DIRECTION, Specified required Rejection Direction ... + * @param bullishRejectUpperPriceType: ENUM_X_PRICE, Specified Bullish Rejection Upper Price Type ... + * @param bullishRejectLowerPriceType: ENUM_X_PRICE, Specified Bullish Rejection Lower Price Type ... + * @param bearishRejectUpperPriceType: ENUM_X_PRICE, Specified Bearish Rejection Upper Price Type ... + * @param bearishRejectLowerPriceType: ENUM_X_PRICE, Specified Bearish Rejection Lower Price Type ... + * @param ignoreBoundary: bool, ignoring XFIMA Max and Min Values Rejections ... + * + * @return ( int ) + */ + int IsRejectXFIMA( + XOHCL &bar, + double &rejecteds[], + ENUM_X_DIRECTION forDir, + ENUM_X_PRICE bullishRejectUpperPriceType = X_PRICE_DOWN, + ENUM_X_PRICE bullishRejectLowerPriceType = X_PRICE_LOW, + ENUM_X_PRICE bearishRejectUpperPriceType = X_PRICE_HIGH, + ENUM_X_PRICE bearishRejectLowerPriceType = X_PRICE_UP, + bool ignoreBoundary = true // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(rejecteds); + + // + // Validate ... + bool has = + bar.IsValid() && + fimaParser.IsValid() && + HasDirection(forDir) && + IsXValid(bullishRejectLowerPriceType) && + IsXValid(bullishRejectUpperPriceType) && + IsXValid(bearishRejectUpperPriceType) && + IsXValid(bearishRejectLowerPriceType); + if (!has) + { + return result; + } + + // + int pBarIndex = bar.Index() + 1; + bool isBullish = IsXBullish(forDir); + + // + // Reading Values ... + double values[]; + int count = fimaParser.ReadXFIMAValues(values, pBarIndex); + has = HasChild(values); + + // + // Detect Rejected Prices ... + if (has) + { + // + double min = GetMin(values); + double max = GetMax(values); + + // + for (int i = 0; i < count; i++) + { + // + // Detect Rejection ... + has = + isBullish + ? (bar.GetPrice(bullishRejectLowerPriceType) < values[i] && + bar.GetPrice(bullishRejectUpperPriceType) > values[i]) + : (bar.GetPrice(bearishRejectUpperPriceType) > values[i] && + bar.GetPrice(bearishRejectLowerPriceType) < values[i]); + if (has) + { + // + // Validate Rejection ... + if (ignoreBoundary) + { + // + has = + has && + (values[i] != min && + values[i] != max); + } + + // + // Add Result ... + if (has) + { + Add(values[i], rejecteds); + } + } + } + } + + // + result = ArraySize(rejecteds); + + // + return result; + } + + // + // Others ... + + /** + * Destroy ... + */ + void Destroy() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + + // + ZeroMemory(fimaHelper); + ZeroMemory(fimaParser); + } + + // + // Testers ... + + // + // Protected ... + protected: + // + // Props ... + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..e7b785e --- /dev/null +++ b/BKPS/14041018/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 @@ -0,0 +1,708 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAPoiDrawer ... +// Description: XFIMA 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 XFIMA POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.xfima.lib.mq5" + +// +// Implementation ... +class XCXFIMAPOIDrawer : public XCPOIDrawer +{ + // + public: + // + // Props ... + + // + // Tested Zones ... + color testedBullishColor; + color testedBearishColor; + + // + // Breaked Zones ... + color breakedBullishColor; + color breakedBearishColor; + + // + // FakeBreaked Zones ... + color fakeBreakedBullishColor; + color fakeBreakedBearishColor; + + // + // Constructor ... + XCXFIMAPOIDrawer() : XCPOIDrawer() + { + Default(); + } + + // + // Deconstructor ... + ~XCXFIMAPOIDrawer() + { + } + + // + // Overrides ... + + /** + * Do additional Configurations for Child Classes ... + */ + void virtual Default() override + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrAqua; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrMagenta; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + + // + testedBullishColor = clrLime; + breakedBullishColor = clrGreen; + fakeBreakedBullishColor = clrYellow; + + // + testedBearishColor = clrRed; + breakedBearishColor = clrDarkRed; + fakeBreakedBearishColor = clrDarkOrange; + } + + // + // Get Specified Directional Arrow Anchor ... + ENUM_ARROW_ANCHOR GetArrowAnchor(ENUM_X_DIRECTION forDir) + { + // + ENUM_ARROW_ANCHOR result = ANCHOR_BOTTOM; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + int GetArrowCode(ENUM_X_DIRECTION forDir) + { + // + int result = 159; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? 233 + : 234; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + color GetArrowColor(ENUM_X_DIRECTION forDir) + { + // + color result = clrYellow; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? clrAqua + : clrMagenta; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Price Type ... + ENUM_X_PRICE GetArrowPriceType(ENUM_X_DIRECTION forDir) + { + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? X_PRICE_LOW + : X_PRICE_HIGH; + } + + // + return result; + } + + /** + * Get Tested Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetTestedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? testedBullishColor + : testedBearishColor; + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetPatternStyle( + style, + zone.dir // + ); + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param forDir: Specified Direction ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + forDir // + ); + + // + style.width = 2; + style.style = STYLE_DASH; + + // + return result; + } + + /** + * Get Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? breakedBullishColor + : breakedBearishColor; + + // + return result; + } + + /** + * Get Fake Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetFakeBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? fakeBreakedBullishColor + : fakeBreakedBearishColor; + + // + return result; + } + + /** + * Fill Arrow Based Drawing Specs ... + * + * @param forDir: Specified Direction ... + * @param arrowPriceType: ENUM_X_PRICE, refrence for Arrow Price ... + * @param arrowCode: int, reference for Arrow Code ... + * @param arrowWidth: int, reference for Arrow Width ... + * @param arrowColor: color, reference for Arrow Color ... + * @param arrowAnchor: ENUM_ARROW_ANCHOR, reference for Arrow Anchor ... + */ + void FillArrowSpecs( + ENUM_X_DIRECTION forDir, + ENUM_X_PRICE &arrowPriceType, + int &arrowCode, + int &arrowWidth, + color &arrowColor, + ENUM_ARROW_ANCHOR &arrowAnchor // + ) + { + // + // Prepare ... + arrowCode = 159; + arrowWidth = 2; + arrowColor = CLR_NONE; + arrowAnchor = ANCHOR_BOTTOM; + arrowPriceType = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + arrowCode = GetArrowCode(forDir); + arrowColor = GetArrowColor(forDir); + arrowAnchor = GetArrowAnchor(forDir); + arrowPriceType = GetArrowPriceType(forDir); + } + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyTestedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetTestedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Breaked Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyBreakedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyFakeBreakStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetFakeBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Pattern Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPatternStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetPatternStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPatternsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBoxObject *iBoxObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iBoxObj = (XCBoxObject *)objects.At(i); + iName = iBoxObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + /** + * Apply Style to Specified Pivot Object ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPivotStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPivotsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBarArrowObject *iObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iObj = (XCBarArrowObject *)objects.At(i); + iName = iObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyPivotStyle( + iObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iObj); + } + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 b/BKPS/14041018/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 new file mode 100644 index 0000000..00d7994 --- /dev/null +++ b/BKPS/14041018/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 @@ -0,0 +1,590 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCXFIMAEALib ... +// Description: XFIMAEA Library ... +// +// +// 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 XFIMAEA Library" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" + +// +// Definitions ... + +/** + * XFIMA Base Market Structure ... + * AnalyseMarket result ... + **/ +struct XFIMAMarketStructure +{ + // + XOHCL bar; // Spacified Start Bar for Analysing ... + XPatternAnalysis barAnalysis; // Structure Bar Pattern Analysis ... + + // + XBoxZone orderFlow[]; // Specified Order Flow Zones ... + ENUM_X_DIRECTION orderFlowDir; // Specified Order Flow Direction ... + + // + XPivot pvPivots[]; // XPV Pivots ... + XPivot zgPivots[]; // XZG Pivots ... + XPivot maPivots[]; // XMA Pivots ... + XPivot hkPivots[]; // XHK Pivots ... + XPivot sarPivots[]; // XSAR Pivots ... + + // + XPivotAnalysis pvAnalysis; // XPV Pivot Analysis Result ... + XPivotAnalysis zgAnalysis; // XZG Pivot Analysis Result ... + XPivotAnalysis maAnalysis; // XMA Pivot Analysis Result ... + XPivotAnalysis hkAnalysis; // XHK Pivot Analysis Result ... + XPivotAnalysis sarAnalysis; // XSAR Pivot Analysis Result ... + + // + XPatternAnalysis barsAnalysis[]; // Anaysed Bars ... + + // + // Constructor ... + XFIMAMarketStructure() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + bar.Clean(); + barAnalysis.Clean(); + + // + XClean(pvPivots); + XClean(zgPivots); + XClean(maPivots); + XClean(hkPivots); + XClean(sarPivots); + + // + pvAnalysis.Clean(); + zgAnalysis.Clean(); + maAnalysis.Clean(); + hkAnalysis.Clean(); + sarAnalysis.Clean(); + + // + XClean(barsAnalysis); + + // + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = bar.IsValid() && + barAnalysis.IsValid(); + + // + return result; + } + + // + // Checkers ... + + /** + * Check Market Strucutre Has Order Flow or not ... + * + * @return ( bool ) + */ + bool HasOrderFlow() + { + // + bool result = false; + + // + result = IsValid() && + HasChild(orderFlow) && + HasDirection(orderFlowDir); + + // + return result; + } + + /** + * Check Market Structure Has Bullish Order Flow or not ... + * + * @return ( bool ) + */ + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + /** + * Check Market Structure Has Bearish Order Flow or not ... + * + * @return ( bool ) + */ + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + + // + // Collectors ... + + /** + * Collect all Pivots ... + * + * @param dest: XPivot, collection reference to holds result ... + * @param containsPatterns: bool, Specified to Add Pivots Bar Directionl Patterns ... + * @param forDir: ENUM_X_DIRECTION, Specified Extraction Direction ... + * + * @return ( int ) + */ + int CollectPivots( + XPivot &dest[], + bool containsPatterns = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + + // + Copy(pvPivots, dest, false); + Copy(hkPivots, dest, false); + Copy(maPivots, dest, false); + Copy(zgPivots, dest, false); + Copy(sarPivots, dest, false); + + // + // Apply Direction Filtering ... + if (HasDirection(forDir)) + { + // + XPivot tmps[]; + ExtractByDirection( + tmps, + dest, + forDir // + ); + XClean(dest); + Copy(tmps, dest); + XClean(tmps); + } + + // + // Contains Pattern Pivots ... + if (containsPatterns && HasChild(dest) && HasChild(barsAnalysis)) + { + // + XPivot tmp; + int idx = -1; + XPivot tmps[]; + XPivot sames[]; + XPivot patterns[]; + Copy(dest, tmps); + XClean(dest); + + // + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + XClean(sames); + ExtractSameTimePivots(tmp, sames, tmps); + if (HasChild(sames)) + { + // + has = FindByTime(idx, tmp.time, barsAnalysis); + if (has) + { + // + barsAnalysis[idx].GetPatterns(patterns, sames[0].dir); + Copy(patterns, dest, false); + } + + // + Copy(sames, dest, false); + Removes(sames, tmps); + } + } + + // + XClean(tmps); + XClean(sames); + XClean(patterns); + } + + // + result = ArraySize(dest); + + // + return result; + } + + // +}; + +/** + * Configure How to Detect Market Structure ... + **/ +struct XFIMAMarketStructureConfig +{ + // + // Props ... + + // + // Detector Flags ... + + // + bool analysePVPivots; // Analyse PV Pivots ... + bool analyseZGPivots; // Analyse ZG Pivots ... + bool analyseHKPivots; // Analyse HK Pivots ... + bool analyseMAPivots; // Analyse MA Pivots ... + bool analyseSARPivots; // Analyse SAR Pivots ... + + // + bool analyseBarPatterns; // Analyse Bar Patterns ... + + // + bool detectOrderFlow; // Detect Order Flow ... + + // + // Detector Configs ... + + // + int loopback; // Max Allowed Looping Back Length ... + int requiredPivots; // Required Extracted Pivots for Analysis ... + + // + int orderFlowValidation; // Order Flow Sequential Validation ... + bool orderFlowUseOB; // Order Flow Use Order Blocks ... + bool orderFlowUseFVG; // Order Flow Use Fair Value Gaps ... + bool orderFlowUseSupportAndResistance; // Order Flow Use Support and Resistance (s) ... + + // + XPatternAnalysisConfig barsAnalysisConfig; // Bars Analyser Config ... + + // + // Constructor ... + XFIMAMarketStructureConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Detector Flags ... + detectOrderFlow = false; + analysePVPivots = false; + analyseZGPivots = false; + analyseHKPivots = false; + analyseMAPivots = false; + analyseSARPivots = false; + analyseBarPatterns = false; + + // + // Configure Detectors ... + loopback = 0; + requiredPivots = 0; + + // + orderFlowValidation = 0; + orderFlowUseOB = false; + orderFlowUseFVG = false; + orderFlowUseSupportAndResistance = false; + + // + barsAnalysisConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Detector Flags ... + detectOrderFlow = true; + analysePVPivots = true; + analyseZGPivots = true; + analyseHKPivots = true; + analyseMAPivots = true; + analyseSARPivots = true; + analyseBarPatterns = true; + + // + // Configure Detectors ... + loopback = 200; + requiredPivots = 10; + + // + orderFlowValidation = 2; + orderFlowUseOB = false; + orderFlowUseFVG = true; + orderFlowUseSupportAndResistance = false; + + // + barsAnalysisConfig.Default(); + barsAnalysisConfig.FullPattern(); + + // + barsAnalysisConfig.supportAndResistanceLoopbackLength = 5; + barsAnalysisConfig.supportAndResistanceValidationLength = 11; + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + // Detector Flags ... + detectOrderFlow = false; + analysePVPivots = false; + analyseZGPivots = false; + analyseHKPivots = false; + analyseMAPivots = false; + analyseSARPivots = false; + analyseBarPatterns = false; + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + // Detector Flags ... + detectOrderFlow = true; + analysePVPivots = true; + analyseZGPivots = true; + analyseHKPivots = true; + analyseMAPivots = true; + analyseSARPivots = true; + analyseBarPatterns = true; + } + + // +}; + +/** + * Configure Market Structure Drawer ... + **/ +struct XFIMAMarketStructureDrawerConfig +{ + // + // Props ... + + // + bool drawPVAnalysis; + bool drawZGAnalysis; + bool drawMAAnalysis; + bool drawHKAnalysis; + bool drawSARAnalysis; + bool drawBarsAnalysis; + + // + XPOIDrawConfig drawConfig; + XPivotAnalysisDrawConfig pivotAnalysisDrawConfig; + XPatternAnalysisDrawConfig barAnalysisDrawConfig; + + // + // Constructor ... + XFIMAMarketStructureDrawerConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawMAAnalysis = false; + drawHKAnalysis = false; + drawSARAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + drawConfig.Clean(); + barAnalysisDrawConfig.Clean(); + pivotAnalysisDrawConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = true; + drawZGAnalysis = true; + drawMAAnalysis = true; + drawHKAnalysis = true; + drawSARAnalysis = true; + drawBarsAnalysis = true; + + // + // Drawing Configs ... + drawConfig.Default(); + pivotAnalysisDrawConfig.Default(); + + // + barAnalysisDrawConfig.Default(); + barAnalysisDrawConfig.Full(); + XClean(barAnalysisDrawConfig.allowedDrawZones); + Add( + X_BAR_PATTERN_SUPPORT, + barAnalysisDrawConfig.allowedDrawZones); + Add( + X_BAR_PATTERN_RESISTANCE, + barAnalysisDrawConfig.allowedDrawZones); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawMAAnalysis = false; + drawHKAnalysis = false; + drawSARAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + barAnalysisDrawConfig.Off(); + pivotAnalysisDrawConfig.Off(); + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = true; + drawZGAnalysis = true; + drawMAAnalysis = true; + drawHKAnalysis = true; + drawSARAnalysis = true; + drawBarsAnalysis = true; + + // + // Drawing Configs ... + barAnalysisDrawConfig.Full(); + pivotAnalysisDrawConfig.Full(); + } + + void ApplyDrawConfig() + { + // + barAnalysisDrawConfig.drawConfig = drawConfig; + pivotAnalysisDrawConfig.drawConfig = drawConfig; + } + + void ApplyDrawConfig(XPOIDrawConfig &_drawConfig) + { + // + drawConfig = _drawConfig; + ApplyDrawConfig(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14041018/XOM1EA/Classes/xom1ea.expert.class.mq5 b/BKPS/14041018/XOM1EA/Classes/xom1ea.expert.class.mq5 new file mode 100644 index 0000000..75966de --- /dev/null +++ b/BKPS/14041018/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -0,0 +1,1097 @@ +/////////////////////////////////////////////////////// +// +// 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-target.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 ... + XCTarget *eaTarget; // EA Scope Target Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + XCTradeManager *eaTradeManager; // EA Scope Trade Handler ... + + // + // 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, + eaTarget // + ); + + // + // 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/14041018/XOM1EA/Classes/xom1ea.signaller.class.mq5 b/BKPS/14041018/XOM1EA/Classes/xom1ea.signaller.class.mq5 new file mode 100644 index 0000000..0fc24ab --- /dev/null +++ b/BKPS/14041018/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/14041018/XOM1EA/Classes/xom1ea.x-poi.drawer.class.mq5 b/BKPS/14041018/XOM1EA/Classes/xom1ea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..52807c9 --- /dev/null +++ b/BKPS/14041018/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.ApplyTrendLineStyle( + 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.ApplyTrendLineStyle( + 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.ApplyLineStyle( + 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/14041018/XOM1EA/Libraries/xom1ea.lib.mq5 b/BKPS/14041018/XOM1EA/Libraries/xom1ea.lib.mq5 new file mode 100644 index 0000000..9652bb0 --- /dev/null +++ b/BKPS/14041018/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/14041018/compile.cmd b/BKPS/14041018/compile.cmd new file mode 100644 index 0000000..54ad737 --- /dev/null +++ b/BKPS/14041018/compile.cmd @@ -0,0 +1,29 @@ +@echo off + + set METAEDITOR="C:\Program Files\MetaTrader 5\MetaEditor64.exe" + @REM set METAEDITOR="C:\Program Files\MetaTrader 5 General\MetaEditor64.exe" + @REM set METAEDITOR="C:\Program Files\MetaTrader 5 Main\MetaEditor64.exe" + @REM 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/14041018/hpi7.compiler.path.cmd b/BKPS/14041018/hpi7.compiler.path.cmd new file mode 100644 index 0000000..26650e0 --- /dev/null +++ b/BKPS/14041018/hpi7.compiler.path.cmd @@ -0,0 +1 @@ +set METAEDITOR="C:\Program Files\MetaTrader 5 General\MetaEditor64.exe" \ No newline at end of file diff --git a/BKPS/14041018/imacslim.compiler.path.cmd b/BKPS/14041018/imacslim.compiler.path.cmd new file mode 100644 index 0000000..8d08458 --- /dev/null +++ b/BKPS/14041018/imacslim.compiler.path.cmd @@ -0,0 +1 @@ +set METAEDITOR="C:\Program Files\MetaTrader 5 Main\MetaEditor64.exe" \ No newline at end of file diff --git a/BKPS/14041018/mqlHelper.js b/BKPS/14041018/mqlHelper.js new file mode 100644 index 0000000..8fe4e41 --- /dev/null +++ b/BKPS/14041018/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/14041018/package-lock.json b/BKPS/14041018/package-lock.json new file mode 100644 index 0000000..34ad997 --- /dev/null +++ b/BKPS/14041018/package-lock.json @@ -0,0 +1,185 @@ +{ + "name": "mql5", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "requires": { + "hasown": "^2.0.2" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "requires": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shx": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", + "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", + "dev": true, + "requires": { + "minimist": "^1.2.3", + "shelljs": "^0.8.5" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + } + } +} diff --git a/BKPS/14041018/package.json b/BKPS/14041018/package.json new file mode 100644 index 0000000..bef7961 --- /dev/null +++ b/BKPS/14041018/package.json @@ -0,0 +1,34 @@ +{ + "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", + "repackXFIMAEA": "node prepareXFIMAEA.js", + "repackXCATBEA": "node prepareXCATBEA.js", + "repackXOM1EA": "node prepareXOM1EA.js", + "repackXRRTools": "node prepareXRRTools.js", + "repackX121XKIEA": "node prepareX121XKIEA.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/14041018/prepareX121XKIEA.js b/BKPS/14041018/prepareX121XKIEA.js new file mode 100644 index 0000000..a147dd5 --- /dev/null +++ b/BKPS/14041018/prepareX121XKIEA.js @@ -0,0 +1,29 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "X121XKIEA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "X121XKIEA/*", // X121XKIEA Projects ... + "Indicators/x-saherelm.x121.xki", // Required Indicators + "Helpers/x-saherelm.x121.xki.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.x121.xki.backtester.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject(projectName, projectResources); +} diff --git a/BKPS/14041018/prepareXCATBEA.js b/BKPS/14041018/prepareXCATBEA.js new file mode 100644 index 0000000..797e213 --- /dev/null +++ b/BKPS/14041018/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/14041018/prepareXFIMAEA.js b/BKPS/14041018/prepareXFIMAEA.js new file mode 100644 index 0000000..b1dd080 --- /dev/null +++ b/BKPS/14041018/prepareXFIMAEA.js @@ -0,0 +1,31 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XFIMAEA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "XFIMAEA/*", // XOM1EA Projects ... + "Indicators/x-saherelm.xfima", // Required Indicators + "Indicators/x-saherelm.x121.xct", // Required Indicators + "Helpers/x-saherelm.xfima.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.xfima.backtester.ea", // Expert Advisers + "Experts/x-saherelm.xfima.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject(projectName, projectResources); +} diff --git a/BKPS/14041018/prepareXOM1EA.js b/BKPS/14041018/prepareXOM1EA.js new file mode 100644 index 0000000..82f073d --- /dev/null +++ b/BKPS/14041018/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/14041018/prepareXRRTools.js b/BKPS/14041018/prepareXRRTools.js new file mode 100644 index 0000000..b6597dd --- /dev/null +++ b/BKPS/14041018/prepareXRRTools.js @@ -0,0 +1,27 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XRRTools"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "Indicators/x-saherelm.x121.xcc", // Required Indicators + "Experts/x-saherelm.rr.tools", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject(projectName, projectResources); +} diff --git a/BKPS/14041018/x-mql-project.tools.js b/BKPS/14041018/x-mql-project.tools.js new file mode 100644 index 0000000..25534e6 --- /dev/null +++ b/BKPS/14041018/x-mql-project.tools.js @@ -0,0 +1,497 @@ +/** + * 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 + "XOM1EA", // XOM1EA Projects ... + "XFIMAEA", // XOM1EA Projects ... + "XCATBEA", // XCATBEA Projects ... + "X121XKIEA", // X121XKIEA 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