From 57371b9343663ed51ebb1529382ce4b56703a45f Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 21 May 2024 04:36:05 +0330 Subject: [PATCH] complete xea class ... --- Classes/x-saherelm.base.class.mq5 | 5 +- Classes/x-saherelm.x5.provider.class.mq5 | 2 +- Classes/x-saherelm.xalert.class.mq5 | 1363 ++++++++++++++++++++++ Classes/x-saherelm.xea.class.mq5 | 1154 ++++++++++++++++++ Classes/x-saherelm.xhttp.class.mq5 | 373 ++++++ Classes/x-saherelm.xtrade.class.mq5 | 4 +- Documents/x-test.x5ea.mq5 | 2 - Experts/x-test.x5ea.mq5 | 4 - Indicators/x-saherelm.xchlh.mq5 | 4 - Indicators/x-saherelm.xmc.mq5 | 31 +- Libraries/x-saherelm.alert.lib.mq5 | 187 --- Libraries/x-saherelm.common.lib.mq5 | 76 +- Libraries/x-saherelm.http.lib.mq5 | 177 --- Libraries/x-saherelm.log.lib.mq5 | 1084 ----------------- Libraries/x-saherelm.xtrade.lib.mq5 | 266 +++++ 15 files changed, 3227 insertions(+), 1505 deletions(-) create mode 100644 Classes/x-saherelm.xalert.class.mq5 create mode 100644 Classes/x-saherelm.xea.class.mq5 create mode 100644 Classes/x-saherelm.xhttp.class.mq5 delete mode 100644 Libraries/x-saherelm.alert.lib.mq5 delete mode 100644 Libraries/x-saherelm.http.lib.mq5 delete mode 100644 Libraries/x-saherelm.log.lib.mq5 diff --git a/Classes/x-saherelm.base.class.mq5 b/Classes/x-saherelm.base.class.mq5 index dde713e7..cde0dd8e 100644 --- a/Classes/x-saherelm.base.class.mq5 +++ b/Classes/x-saherelm.base.class.mq5 @@ -35,10 +35,10 @@ public: // // Represent Basic Unique Tag ... virtual string GetTag(); -protected: + // // Retrieve Class Token ... - string GetToken() + virtual string GetToken() { // string result = NULL; @@ -81,6 +81,7 @@ protected: return result; } +protected: // // Private ... private: diff --git a/Classes/x-saherelm.x5.provider.class.mq5 b/Classes/x-saherelm.x5.provider.class.mq5 index a4453983..21a66c9a 100644 --- a/Classes/x-saherelm.x5.provider.class.mq5 +++ b/Classes/x-saherelm.x5.provider.class.mq5 @@ -2035,7 +2035,7 @@ public: // For Data Collector ... string GetToken() { - return GetToken(this); + return GetSpecificToken(this); } bool IsModelValid() { diff --git a/Classes/x-saherelm.xalert.class.mq5 b/Classes/x-saherelm.xalert.class.mq5 new file mode 100644 index 00000000..de28ce21 --- /dev/null +++ b/Classes/x-saherelm.xalert.class.mq5 @@ -0,0 +1,1363 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAlert +// Description: provides all Alerts requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Class Definition ... + +class XSCAlert : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + XSCAlert() {} + XSCAlert( + string prefix = "X-Alert", // Alerts Prefixe + bool enableAlerts = true, // Enable Alerts + bool logAlerts = true, // Log Alerts + bool terminalAlerts = false, // Terminal Alerts + bool mailAlerts = false, // Mail Alerts + bool pushAlerts = false // Push Alerts + ) + { + // + mPrefix = prefix; + mLogAlerts = logAlerts; + mMailAlerts = mailAlerts; + mPushAlerts = pushAlerts; + mEnableAlerts = enableAlerts; + mTerminalAlerts = terminalAlerts; + + // + // Normalize Prefix if Not Provided ... + if (!IsValid(mPrefix)) + { + mPrefix = GetTag(); + } + } + + // + // Deconstructor ... + ~XSCAlert() {} + + // + // Override ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Properties Getter(s) / Setter(s) ... + + // + string GetPrefix() + { + return mPrefix; + } + + // + void SetPrefix(string value) + { + mPrefix = value; + } + + // + bool GetLogAlerts() + { + return mLogAlerts; + } + + // + void SetLogAlerts(bool value) + { + mLogAlerts = value; + } + + // + bool GetEnableAlerts() + { + return mEnableAlerts; + } + + // + void SetEnableAlerts(bool value) + { + mEnableAlerts = value; + } + + // + bool GetPushAlerts() + { + return mPushAlerts; + } + + // + void SetPushAlerts(bool value) + { + mPushAlerts = value; + } + + // + bool GetMailAlerts() + { + return mMailAlerts; + } + + // + void SetMailAlerts(bool value) + { + mMailAlerts = value; + } + + // + bool GetTerminalAlerts() + { + return mTerminalAlerts; + } + + // + void SetTerminalAlerts(bool value) + { + mTerminalAlerts = value; + } + + // + // Tools Funtions ... + + // + // Alerts ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + // + // Validate Args ... + if (!CanLogAlert()) + { + return; + } + + // + Log(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + // + // Validate Args ... + if (!CanTerminalAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // Send Terminal Alert ... + Alert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + // + // Validate Args ... + if (!CanMailAlert()) + { + return; + } + + // + // Send Mail Alert ... + SendMail(GetPrefix(), message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + // + // Validate Args ... + if (!CanPushAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void Alert(string message) + { + // + // Handle Log, if Enabled ... + LogAlert(message); + + // + // Handle Mail if Enabled ... + MailAlert(message); + + // + // Handle Push if Enabled ... + PushAlert(message); + + // + // Handle Terminal if Enabled ... + TerminalAlert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), " > ", message); + } + void Log(string tag, string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), "_", tag, " > ", message); + } + void LogEmpty() + { + // + if (!CanLog()) + { + return; + } + + // + Print(" "); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), ">", (IsValid(label) ? label : "")); + ArrayPrint(array); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + // + if (!CanLog()) + { + return; + } + + // + if (error <= -1) + { + error = GetLastError(); + } + + // + string errorMsg = GetErrorDescription(error); + + // + Log("Error: " + errorMsg); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + // + string result = ""; + + // + switch (err_code) + { + // + //--- Constant Description + + // + case ERR_SUCCESS: + result = "The operation completed successfully"; + break; + + // + case ERR_INTERNAL_ERROR: + result = "Unexpected internal error"; + break; + + // + case ERR_WRONG_INTERNAL_PARAMETER: + result = "Wrong parameter in the inner call of the client terminal function"; + break; + + // + case ERR_INVALID_PARAMETER: + result = "Wrong parameter when calling the system function"; + break; + + // + case ERR_NOT_ENOUGH_MEMORY: + result = "Not enough memory to perform the system function"; + break; + + // + case ERR_STRUCT_WITHOBJECTS_ORCLASS: + result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"; + break; + + // + case ERR_INVALID_ARRAY: + result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array"; + break; + + // + case ERR_ARRAY_RESIZE_ERROR: + result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"; + break; + + // + case ERR_STRING_RESIZE_ERROR: + result = "Not enough memory for the relocation of string"; + break; + + // + case ERR_NOTINITIALIZED_STRING: + result = "Not initialized string"; + break; + + // + case ERR_INVALID_DATETIME: + result = "Invalid date and/or time"; + break; + + // + case ERR_ARRAY_BAD_SIZE: + result = "Requested array size exceeds 2 GB"; + break; + + // + case ERR_INVALID_POINTER: + result = "Wrong pointer"; + break; + + // + case ERR_INVALID_POINTER_TYPE: + result = "Wrong type of pointer"; + break; + + // + case ERR_FUNCTION_NOT_ALLOWED: + result = "System function is not allowed to call"; + break; + + // + //--- Charts + + // + case ERR_CHART_WRONG_ID: + result = "Wrong chart ID"; + break; + + // + case ERR_CHART_NO_REPLY: + result = "Chart does not respond"; + break; + + // + case ERR_CHART_NOT_FOUND: + result = "Chart not found"; + break; + + // + case ERR_CHART_NO_EXPERT: + result = "No Expert Advisor in the chart that could handle the event"; + break; + + // + case ERR_CHART_CANNOT_OPEN: + result = "Chart opening error"; + break; + + // + case ERR_CHART_CANNOT_CHANGE: + result = "Failed to change chart symbol and period"; + break; + + // + case ERR_CHART_CANNOT_CREATE_TIMER: + result = "Failed to create timer"; + break; + + // + case ERR_CHART_WRONG_PROPERTY: + result = "Wrong chart property ID"; + break; + + // + case ERR_CHART_SCREENSHOT_FAILED: + result = "Error creating screenshots"; + break; + + // + case ERR_CHART_NAVIGATE_FAILED: + result = "Error navigating through chart"; + break; + + // + case ERR_CHART_TEMPLATE_FAILED: + result = "Error applying template"; + break; + + // + case ERR_CHART_WINDOW_NOT_FOUND: + result = "Subwindow containing the indicator was not found"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_ADD: + result = "Error adding an indicator to chart"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_DEL: + result = "Error deleting an indicator from the chart"; + break; + + // + case ERR_CHART_INDICATOR_NOT_FOUND: + result = "Indicator not found on the specified chart"; + break; + + // + //--- Graphical Objects + case ERR_OBJECT_ERROR: + result = "Error working with a graphical object"; + break; + + // + case ERR_OBJECT_NOT_FOUND: + result = "Graphical object was not found"; + break; + + // + case ERR_OBJECT_WRONG_PROPERTY: + result = "Wrong ID of a graphical object property"; + break; + + // + case ERR_OBJECT_GETDATE_FAILED: + result = "Unable to get date corresponding to the value"; + break; + + // + case ERR_OBJECT_GETVALUE_FAILED: + result = "Unable to get value corresponding to the date"; + break; + + // + //--- MarketInfo + + // + case ERR_MARKET_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_MARKET_NOT_SELECTED: + result = "Symbol is not selected in MarketWatch"; + break; + + // + case ERR_MARKET_WRONG_PROPERTY: + result = "Wrong identifier of a symbol property"; + break; + + // + case ERR_MARKET_LASTTIME_UNKNOWN: + result = "Time of the last tick is not known (no ticks)"; + break; + + // + case ERR_MARKET_SELECT_ERROR: + result = "Error adding or deleting a symbol in MarketWatch"; + break; + + // + //--- History Access + + // + case ERR_HISTORY_NOT_FOUND: + result = "Requested history not found"; + break; + + // + case ERR_HISTORY_WRONG_PROPERTY: + result = "Wrong ID of the history property"; + break; + + // + //--- Global_Variables + + // + case ERR_GLOBALVARIABLE_NOT_FOUND: + result = "Global variable of the client terminal is not found"; + break; + + // + case ERR_GLOBALVARIABLE_EXISTS: + result = "Global variable of the client terminal with the same name already exists"; + break; + + // + case ERR_MAIL_SEND_FAILED: + result = "Email sending failed"; + break; + + // + case ERR_PLAY_SOUND_FAILED: + result = "Sound playing failed"; + break; + + // + case ERR_MQL5_WRONG_PROPERTY: + result = "Wrong identifier of the program property"; + break; + + // + case ERR_TERMINAL_WRONG_PROPERTY: + result = "Wrong identifier of the terminal property"; + break; + + // + case ERR_FTP_SEND_FAILED: + result = "File sending via ftp failed"; + break; + + // + case ERR_NOTIFICATION_SEND_FAILED: + result = "Error in sending notification"; + break; + + // + //--- Custom Indicator Buffers + + // + case ERR_BUFFERS_NO_MEMORY: + result = "Not enough memory for the distribution of indicator buffers"; + break; + + // + case ERR_BUFFERS_WRONG_INDEX: + result = "Wrong indicator buffer index"; + break; + + // + //--- Custom Indicator Properties + + // + case ERR_CUSTOM_WRONG_PROPERTY: + result = "Wrong ID of the custom indicator property"; + break; + + // + //--- Account + + // + case ERR_ACCOUNT_WRONG_PROPERTY: + result = "Wrong account property ID"; + break; + + // + case ERR_TRADE_WRONG_PROPERTY: + result = "Wrong trade property ID"; + break; + + // + case ERR_TRADE_DISABLED: + result = "Trading by Expert Advisors prohibited"; + break; + + // + case ERR_TRADE_POSITION_NOT_FOUND: + result = "Position not found"; + break; + + // + case ERR_TRADE_ORDER_NOT_FOUND: + result = "Order not found"; + break; + + // + case ERR_TRADE_DEAL_NOT_FOUND: + result = "Deal not found"; + break; + + // + case ERR_TRADE_SEND_FAILED: + result = "Trade request sending failed"; + break; + + // + //--- Indicators + + // + case ERR_INDICATOR_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_INDICATOR_CANNOT_CREATE: + result = "Indicator cannot be created"; + break; + + // + case ERR_INDICATOR_NO_MEMORY: + result = "Not enough memory to add the indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_APPLY: + result = "The indicator cannot be applied to another indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_ADD: + result = "Error applying an indicator to chart"; + break; + + // + case ERR_INDICATOR_DATA_NOT_FOUND: + result = "Requested data not found"; + break; + + // + case ERR_INDICATOR_WRONG_HANDLE: + result = "Wrong indicator handle"; + break; + + // + case ERR_INDICATOR_WRONG_PARAMETERS: + result = "Wrong number of parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_PARAMETERS_MISSING: + result = "No parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_CUSTOM_NAME: + result = "The first parameter in the array must be the name of the custom indicator"; + break; + + // + case ERR_INDICATOR_PARAMETER_TYPE: + result = "Invalid parameter type in the array when creating an indicator"; + break; + + // + case ERR_INDICATOR_WRONG_INDEX: + result = "Wrong index of the requested indicator buffer"; + break; + + // + //--- Depth of Market + + // + case ERR_BOOKS_CANNOT_ADD: + result = "Depth Of Market can not be added"; + break; + + // + case ERR_BOOKS_CANNOT_DELETE: + result = "Depth Of Market can not be removed"; + break; + + // + case ERR_BOOKS_CANNOT_GET: + result = "The data from Depth Of Market can not be obtained"; + break; + + // + case ERR_BOOKS_CANNOT_SUBSCRIBE: + result = "Error in subscribing to receive new data from Depth Of Market"; + break; + + // + //--- File Operations + + // + case ERR_TOO_MANY_FILES: + result = "More than 64 files cannot be opened at the same time"; + break; + + // + case ERR_WRONG_FILENAME: + result = "Invalid file name"; + break; + + // + case ERR_TOO_LONG_FILENAME: + result = "Too long file name"; + break; + + // + case ERR_CANNOT_OPEN_FILE: + result = "File opening error"; + break; + + // + case ERR_FILE_CACHEBUFFER_ERROR: + result = "Not enough memory for cache to read"; + break; + + // + case ERR_CANNOT_DELETE_FILE: + result = "File deleting error"; + break; + + // + case ERR_INVALID_FILEHANDLE: + result = "A file with this handle was closed, or was not opening at all"; + break; + + // + case ERR_WRONG_FILEHANDLE: + result = "Wrong file handle"; + break; + + // + case ERR_FILE_NOTTOWRITE: + result = "The file must be opened for writing"; + break; + + // + case ERR_FILE_NOTTOREAD: + result = "The file must be opened for reading"; + break; + + // + case ERR_FILE_NOTBIN: + result = "The file must be opened as a binary one"; + break; + + // + case ERR_FILE_NOTTXT: + result = "The file must be opened as a text"; + break; + + // + case ERR_FILE_NOTTXTORCSV: + result = "The file must be opened as a text or CSV"; + break; + + // + case ERR_FILE_NOTCSV: + result = "The file must be opened as CSV"; + break; + + // + case ERR_FILE_READERROR: + result = "File reading error"; + break; + + // + case ERR_FILE_BINSTRINGSIZE: + result = "String size must be specified, because the file is opened as binary"; + break; + + // + case ERR_INCOMPATIBLE_FILE: + result = "A text file must be for string arrays, for other arrays - binary"; + break; + + // + case ERR_FILE_IS_DIRECTORY: + result = "This is not a file, this is a directory"; + break; + + // + case ERR_FILE_NOT_EXIST: + result = "File does not exist"; + break; + + // + case ERR_FILE_CANNOT_REWRITE: + result = "File can not be rewritten"; + break; + + // + case ERR_WRONG_DIRECTORYNAME: + result = "Wrong directory name"; + break; + + // + case ERR_DIRECTORY_NOT_EXIST: + result = "Directory does not exist"; + break; + + // + case ERR_FILE_ISNOT_DIRECTORY: + result = "This is a file, not a directory"; + break; + + // + case ERR_CANNOT_DELETE_DIRECTORY: + result = "The directory cannot be removed"; + break; + + // + case ERR_CANNOT_CLEAN_DIRECTORY: + result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)"; + break; + + // + case ERR_FILE_WRITEERROR: + result = "Failed to write a resource to a file"; + break; + + // + //--- String Casting + + // + case ERR_NO_STRING_DATE: + result = "No date in the string"; + break; + + // + case ERR_WRONG_STRING_DATE: + result = "Wrong date in the string"; + break; + + // + case ERR_WRONG_STRING_TIME: + result = "Wrong time in the string"; + break; + + // + case ERR_STRING_TIME_ERROR: + result = "Error converting string to date"; + break; + + // + case ERR_STRING_OUT_OF_MEMORY: + result = "Not enough memory for the string"; + break; + + // + case ERR_STRING_SMALL_LEN: + result = "The string length is less than expected"; + break; + + // + case ERR_STRING_TOO_BIGNUMBER: + result = "Too large number, more than ULONG_MAX"; + break; + + // + case ERR_WRONG_FORMATSTRING: + result = "Invalid format string"; + break; + + // + case ERR_TOO_MANY_FORMATTERS: + result = "Amount of format specifiers more than the parameters"; + break; + + // + case ERR_TOO_MANY_PARAMETERS: + result = "Amount of parameters more than the format specifiers"; + break; + + // + case ERR_WRONG_STRING_PARAMETER: + result = "Damaged parameter of string type"; + break; + + // + case ERR_STRINGPOS_OUTOFRANGE: + result = "Position outside the string"; + break; + + // + case ERR_STRING_ZEROADDED: + result = "0 added to the string end, a useless operation"; + break; + + // + case ERR_STRING_UNKNOWNTYPE: + result = "Unknown data type when converting to a string"; + break; + + // + case ERR_WRONG_STRING_OBJECT: + result = "Damaged string object"; + break; + + // + //--- Operations with Arrays + + // + case ERR_INCOMPATIBLE_ARRAYS: + result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"; + break; + + // + case ERR_SMALL_ASSERIES_ARRAY: + result = "The receiving array is declared as AS_SERIES, and it is of insufficient size"; + break; + + // + case ERR_SMALL_ARRAY: + result = "Too small array, the starting position is outside the array"; + break; + + // + case ERR_ZEROSIZE_ARRAY: + result = "An array of zero length"; + break; + + // + case ERR_NUMBER_ARRAYS_ONLY: + result = "Must be a numeric array"; + break; + + // + case ERR_ONEDIM_ARRAYS_ONLY: + result = "Must be a one-dimensional array"; + break; + + // + case ERR_SERIES_ARRAY: + result = "Timeseries cannot be used"; + break; + + // + case ERR_DOUBLE_ARRAY_ONLY: + result = "Must be an array of type double"; + break; + + // + case ERR_FLOAT_ARRAY_ONLY: + result = "Must be an array of type float"; + break; + + // + case ERR_LONG_ARRAY_ONLY: + result = "Must be an array of type long"; + break; + + // + case ERR_INT_ARRAY_ONLY: + result = "Must be an array of type int"; + break; + + // + case ERR_SHORT_ARRAY_ONLY: + result = "Must be an array of type short"; + break; + + // + case ERR_CHAR_ARRAY_ONLY: + result = "Must be an array of type char"; + break; + + // + //--- Operations with OpenCL + + // + case ERR_OPENCL_NOT_SUPPORTED: + result = "OpenCL functions are not supported on this computer"; + break; + + // + case ERR_OPENCL_INTERNAL: + result = "Internal error occurred when running OpenCL"; + break; + + // + case ERR_OPENCL_INVALID_HANDLE: + result = "Invalid OpenCL handle"; + break; + + // + case ERR_OPENCL_CONTEXT_CREATE: + result = "Error creating the OpenCL context"; + break; + + // + case ERR_OPENCL_QUEUE_CREATE: + result = "Failed to create a run queue in OpenCL"; + break; + + // + case ERR_OPENCL_PROGRAM_CREATE: + result = "Error occurred when compiling an OpenCL program"; + break; + + // + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: + result = "Too long kernel name (OpenCL kernel)"; + break; + + // + case ERR_OPENCL_KERNEL_CREATE: + result = "Error creating an OpenCL kernel"; + break; + + // + case ERR_OPENCL_SET_KERNEL_PARAMETER: + result = "Error occurred when setting parameters for the OpenCL kernel"; + break; + + // + case ERR_OPENCL_EXECUTE: + result = "OpenCL program runtime error"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_SIZE: + result = "Invalid size of the OpenCL buffer"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_OFFSET: + result = "Invalid offset in the OpenCL buffer"; + break; + + // + case ERR_OPENCL_BUFFER_CREATE: + result = "Failed to create and OpenCL buffer"; + break; + + // + //--- User-Defined Errors + default: + result = "UNKNOWN Erro ..."; + break; + } + + // + return result; + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + // + string result = ""; + + // + switch (return_code) + { + // + case TRADE_RETCODE_REQUOTE: + result = "Requote"; + break; + + // + case TRADE_RETCODE_REJECT: + result = "Request rejected"; + break; + + // + case TRADE_RETCODE_CANCEL: + result = "Request canceled by trader"; + break; + + // + case TRADE_RETCODE_PLACED: + result = "Order placed"; + break; + + // + case TRADE_RETCODE_DONE: + result = "Request completed"; + break; + + // + case TRADE_RETCODE_DONE_PARTIAL: + result = "Only part of the request was completed"; + break; + + // + case TRADE_RETCODE_ERROR: + result = "Request processing error"; + break; + + // + case TRADE_RETCODE_TIMEOUT: + result = "Request canceled by timeout"; + break; + + // + case TRADE_RETCODE_INVALID: + result = "Invalid request"; + break; + + // + case TRADE_RETCODE_INVALID_VOLUME: + result = "Invalid volume in the request"; + break; + + // + case TRADE_RETCODE_INVALID_PRICE: + result = "Invalid price in the request"; + break; + + // + case TRADE_RETCODE_INVALID_STOPS: + result = "Invalid stops in the request"; + break; + + // + case TRADE_RETCODE_TRADE_DISABLED: + result = "Trade is disabled"; + break; + + // + case TRADE_RETCODE_MARKET_CLOSED: + result = "Market is closed"; + break; + + // + case TRADE_RETCODE_NO_MONEY: + result = "There is not enough money to complete the request"; + break; + + // + case TRADE_RETCODE_PRICE_CHANGED: + result = "Prices changed"; + break; + + // + case TRADE_RETCODE_PRICE_OFF: + result = "There are no quotes to process the request"; + break; + + // + case TRADE_RETCODE_INVALID_EXPIRATION: + result = "Invalid order expiration date in the request"; + break; + + // + case TRADE_RETCODE_ORDER_CHANGED: + result = "Order state changed"; + break; + + // + case TRADE_RETCODE_TOO_MANY_REQUESTS: + result = "Too frequent requests"; + break; + + // + case TRADE_RETCODE_NO_CHANGES: + result = "No changes in request"; + break; + + // + case TRADE_RETCODE_SERVER_DISABLES_AT: + result = "Autotrading disabled by server"; + break; + + // + case TRADE_RETCODE_CLIENT_DISABLES_AT: + result = "Autotrading disabled by client terminal"; + break; + + // + case TRADE_RETCODE_LOCKED: + result = "Request locked for processing"; + break; + + // + case TRADE_RETCODE_FROZEN: + result = "Order or position frozen"; + break; + + // + case TRADE_RETCODE_INVALID_FILL: + result = "Invalid order filling type"; + break; + + // + case TRADE_RETCODE_CONNECTION: + result = "No connection with the trade server"; + break; + + // + case TRADE_RETCODE_ONLY_REAL: + result = "Operation is allowed only for live accounts"; + break; + + // + case TRADE_RETCODE_LIMIT_ORDERS: + result = "The number of pending orders has reached the limit"; + break; + + // + case TRADE_RETCODE_LIMIT_VOLUME: + result = "The volume of orders and positions for the symbol has reached the limit"; + break; + + // + default: + result = "Invalid return code of the trade server"; + break; + } + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... + + // + bool CanLog() + { + return mLogAlerts; + } + + // + bool CanLogAlert() + { + // + bool result = GetEnableAlerts() && GetLogAlerts(); + + // + return result; + } + + // + bool CanTerminalAlert() + { + // + bool result = GetEnableAlerts() && GetTerminalAlerts(); + + // + return result; + } + + // + bool CanMailAlert() + { + // + bool result = GetEnableAlerts() && GetMailAlerts(); + + // + return result; + } + + // + bool CanPushAlert() + { + // + bool result = GetEnableAlerts() && GetPushAlerts(); + + // + return result; + } + +private: + // + // Props ... + string mPrefix; // Alerts Prefixe + bool mEnableAlerts; // Enable Alerts + bool mLogAlerts; // Log Alerts + bool mTerminalAlerts; // Terminal Alerts + bool mMailAlerts; // Mail Alerts + bool mPushAlerts; // Push Alerts + + // + // Tools ... + + // + // Clear Escape String and + // Attach Alert Prefix to Message ... + string PrepareMessage(string message) + { + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, GetPrefix(), " > ", message); + + // + return message; + } +}; \ No newline at end of file diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 new file mode 100644 index 00000000..a7fcefae --- /dev/null +++ b/Classes/x-saherelm.xea.class.mq5 @@ -0,0 +1,1154 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseEA +// Description: provides all Base EA 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.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" + +// +// Class Definition ... + +class XSCBaseEA : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + XSCBaseEA( + // + // XTrade Class Requirements ... + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + int manageInterval, // Manager Check Intervals Seconds + double maxAllowedSpread, // Max Allowed Spred for Opening Trades + int maxAllowedPositions, // Max Allowed Positions + double maxAllowedDrawdownFactor, // Max Allowed Drawdown Factor + // + // Position Management ... + bool allowLong = true, // Allow Long Trades + bool allowShort = true, // Allow Short Trades + double minProfitPerTrade = 0, // Min Profit Per Trade based On Volume Factor (Hedge) + double minProfitPerVolumeFactor = 0, // Min Volume Factor for Calculating Profit (Hedge) + // + // Event Handlers ... + TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler + TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler + TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler + TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler + TOnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler + // + // Log Handler ... + 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 + ) + { + // + // Instance XSCTrade Class ... + mTrader = new XSCTrade( + slippage, + magicNumber, + manageInterval, + maxAllowedSpread, + maxAllowedPositions, + maxAllowedDrawdownFactor + // + ); + + // + mIsInTestMode = IsRunningOnTestMode(); + + // + // Position Management ... + mAllowLong = allowLong; + mAllowShort = allowShort; + mMinProfitPerTrade = minProfitPerTrade; + mMinProfitPerVolumeFactor = minProfitPerVolumeFactor; + + // + // Set Event Handlers ... + mOnStopLossTriggered = onStopLossTriggered; + mOnTakeProfitTriggered = onTakeProfitTriggered; + mOnDealsChangedHandler = onDealsChangedHandler; + mOnOrdersChangedHandler = onOrdersChangedHandler; + mOnPositionsChangedHandler = onPositionsChangedHandler; + mOnTradeStateChangedHandler = onTradeStateChangedHandler; + + // + // Add Event Listeners to XTrade Class if they Provided ... + if (mOnStopLossTriggered != NULL) + { + mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered); + } + + // + if (mOnTakeProfitTriggered != NULL) + { + mTrader.AddOnTakeProfitEventHandler(mOnTakeProfitTriggered); + } + + // + if (mOnDealsChangedHandler != NULL) + { + mTrader.AddOnDealsChangedEventHandler(mOnDealsChangedHandler); + } + + // + if (mOnOrdersChangedHandler != NULL) + { + mTrader.AddOnOrdersChangedEventHandler(mOnOrdersChangedHandler); + } + + // + if (mOnPositionsChangedHandler != NULL) + { + mTrader.AddOnPositionsChangedEventHandler(mOnPositionsChangedHandler); + } + + // + if (mOnTradeStateChangedHandler != NULL) + { + mTrader.AddOnTradeStateChangedEventHandler(mOnTradeStateChangedHandler); + } + + // + // Instantiate Alert Class ... + mAlert = new XSCAlert( + GetTag(), + enableAlerts, + logAlerts, + terminalAlerts, + mailAlerts, + pushAlerts + // + ); + } + + // + // Deconstractor ... + ~XSCBaseEA() {} + + // + // Properties Getter(s) / Setter(s) ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mTrader.GetSlippage(); + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mTrader.GetMagicNumber(); + } + + // + // Retrieve Max Allowed Spread for Trading ... + double GetMaxAllowedSpread() + { + return mTrader.GetMaxAllowedSpread(); + } + + // + // Retrieve Max Allowed Same Time Positions Count ... + int GetMaxAllowedPositions() + { + return mTrader.GetMaxAllowedPositions(); + } + + // + // Retrieve Max Allowed Drawdown for Opening new Trades ... + double GetMaxAllowedDrawdownFactor() + { + return mTrader.GetMaxAllowedDrawdownFactor(); + } + + // + bool GetAllowLong() + { + return mAllowLong; + } + + // + void SetAllowLong(bool value) + { + mAllowLong = value; + } + + // + bool GetAllowShort() + { + return mAllowShort; + } + + // + void SetAllowShort(bool value) + { + mAllowShort = value; + } + + // + double GetMinProfitPerTrade() + { + return mMinProfitPerTrade; + } + + // + void SetMinProfitPerTrade(double value) + { + // + if (value <= 0) + { + value = 0; + } + + // + if (value == mMinProfitPerTrade) + { + return; + } + + // + mMinProfitPerTrade = value; + } + + // + double GetMinProfitPerVolumeFactor() + { + return mMinProfitPerVolumeFactor; + } + + // + void SetMinProfitPerVolumeFactor(double value) + { + // + if (value <= 0) + { + value = 0; + } + + // + if (value == mMinProfitPerVolumeFactor) + { + return; + } + + // + mMinProfitPerVolumeFactor = value; + } + + // + // Alert ... + + // + bool GetLogAlerts() + { + return mAlert.GetLogAlerts(); + } + + // + void SetLogAlerts(bool value) + { + mAlert.SetLogAlerts(value); + } + + // + bool GetEnableAlerts() + { + return mAlert.GetEnableAlerts(); + } + + // + void SetEnableAlerts(bool value) + { + mAlert.SetEnableAlerts(value); + } + + // + bool GetPushAlerts() + { + return mAlert.GetPushAlerts(); + } + + // + void SetPushAlerts(bool value) + { + mAlert.SetPushAlerts(value); + } + + // + bool GetMailAlerts() + { + return mAlert.GetMailAlerts(); + } + + // + void SetMailAlerts(bool value) + { + mAlert.SetMailAlerts(value); + } + + // + bool GetTerminalAlerts() + { + return mAlert.GetTerminalAlerts(); + } + + // + void SetTerminalAlerts(bool value) + { + mAlert.SetTerminalAlerts(value); + } + + // + // Overrides ... + + // + // Customize Token ... + virtual string GetToken() + { + return GetSpecificToken(this); + } + + // + virtual string GetTag() + { + return this.GetToken(); + } + + // + // Virtual Functions ... + + // + // Handle Chart Events ... + virtual void OnChartEvent( + const int id, // event ID + const long &lparam, // long type event parameter + const double &dparam, // double type event parameter + const string &sparam // string type event parameter + ) + { + } + + // + // OnTick Handler ... + virtual void OnTick() + { + // + // First Check For Any Guard Actions ... + // then Handle Guards if Provided ... + XGuard guards[]; + bool hasGuard = CheckForGuard(guards); + if (hasGuard) + { + DoGuards(guards); + } + + // + // Second Check for Position Management or Equity Management + // Actions like Supports or etc ... + bool isIgnored = HandleStateManagement(); + if (isIgnored) + { + return; + } + + // + // Second Check For Signals ... + // then Execute Signals if Provided ... + XSignal signals[]; + int signalsCount = CheckForSignal(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Try to Execute Signals ... + ENUM_X_SIGNAL_EXECUTION_RESULT reasons[]; + int executedSignalsCount = mTrader.ExecuteSignals( + signals, + reasons); + + // + string message = NULL; + if (executedSignalsCount == 0) + { + message = "(" + ToString(signalsCount) + ") Signals Execution Failed ..."; + } + else if (executedSignalsCount < signalsCount) + { + // + int diff = signalsCount - executedSignalsCount; + + // + message = "Failed to Execute (" + ToString(diff) + ") Signals ..."; + } + else if (executedSignalsCount == signalsCount) + { + message = "(" + ToString(executedSignalsCount) + ") Signals Executed Successfully ..."; + } + + // + if (IsValid(message)) + { + mAlert.Alert(message); + } + } + + // + // Handle StopLoss Event ... + virtual void OnStopLossTriggered(const XDeal &deal) {} + + // + // Handle TakeProfit Event ... + virtual void OnTakeProfitTriggered(const XDeal &deal) {} + + // + // Handle Deals Changed Event ... + virtual void OnDealsChangedHandler(int count) {} + + // + // Handle Order Changed Event ... + virtual void OnOrdersChangedHandler(int count) {} + + // + // Handle Position Changed Event ... + virtual void OnPositionsChangedHandler(int count) {} + + // + // Handle Trade State Changed ... + virtual void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) {} + + // + // Handle On Trade ... + virtual void OnTrade() + { + // + XOnTradeHandlerState state = mTrader.HandleOnTrade(); + + // + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return; + } + + // + // STATE ... + + // + // Notfy Trade State Changed Event ... + OnTradeStateChangedHandler(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + OnDealsChangedHandler(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + mTrader.GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + OnTakeProfitTriggered(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + OnStopLossTriggered(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + OnOrdersChangedHandler(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + OnPositionsChangedHandler(state.newPositions); + } + } + + // + // Retrieve Dept Of Market ... + virtual void OnBookEvent(const string &symbol) + { + // + // TODO: Implement this ... + } + + // + // Check For any Guard Actions ... + virtual bool CheckForGuard(XGuard &guards[]) + { + return false; + } + + // + // When a Guard Notified to Do Support Signal ... + // this Method Calls For Retrieve Support Signal ... + // if it's Provided, Execute it ... + virtual bool CheckForSupport( + XSignal &support, // Holds Support Signal, if Provided + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + return false; + } + + // + // Handle Position(s)/ Order(s) or EQM Supporting Action ... + // if returns false, prevent for process Tick ... + virtual bool HandleStateManagement() + { + return false; + } + + // + // Here we Have to Check Market based + // on our Strategy for Trading ... + // and if a Good Entry founded ... + // model it as an XSignal struct and passed it to result ... + virtual int CheckForSignal( + XSignal &signals[] // Holds Signals ... + ) + { + return 0; + } + + // + // Protected ... +protected: + // + // Props ... + + // + // Position Management ... + + // + // Calculate Required Profit for Hedging ... + double CalculateRequiredProfitForHedge( + XPosition &positions[] // Source + ) + { + // + 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; + } + + // + // Calculate Positions Profit Summary ... + double CalculatePositionsProfit( + 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; + } + + // + // Guards ... + + // + // Do All Provided Guards ... + void DoGuards(XGuard &guards[]) + { + // + int guardsCount = ArraySize(guards); + if (guardsCount <= 0) + { + return; + } + + // + for (int i = 0; i < guardsCount; i++) + { + // + XGuard iGuard = guards[i]; + + // + switch (iGuard.action) + { + // + // Hedge In Profit Specified Positions ... + case X_GUARD_ACTION_HEDGE: + HandleGuardHedgeAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Trail Stop Loss in Specified Positions ... + case X_GUARD_ACTION_TRAIL_STOP: + HandleGuardTrailingStopAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period, + iGuard.dblPayLoad); + break; + + // + // Force Close Specified Positions ... + case X_GUARD_ACTION_FORCE_CLOSE: + HandleGuardForceCloseAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Generate and Place Support Signals ... + case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL: + HandleGuardAddSupportPositionAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Delete All Placed Pending Orders ... + case X_GUARD_ACTION_CANCEL_PENDING_ORDERS: + HandleGuardCancelPendingOrdersAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + } + } + } + + // + // Close All Specified Provider's Positions in Profit Summary ... + void HandleGuardHedgeAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double minProfitForHedging = 1 // Specified Profit for Hedge + ) + { + // + XPosition positions[]; + int positionsCount = mTrader + .GetPositions( + positions, + symbol, + provider, + period, + type + // + ); + if (positionsCount <= 1) + { + return; + } + + // + double profit = CalculatePositionsProfit(positions); + double requiredProfit = CalculateRequiredProfitForHedge(positions); + + // + bool isReadyForHedge = profit >= requiredProfit; + if (!isReadyForHedge) + { + return; + } + + // + string comment = "Guard Hedge " + provider; + int closed = mTrader.Close( + positions, + comment + // + ); + if (closed > 0) + { + // + string message = "Guard Hedge " + provider + "'s Positions on Profit: " + ToString(profit); + + // + mAlert.Alert(message); + } + } + + // + // Close Max In Profit Trade Guard Action ... + void HandleGuardCloseInProfitAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method + ) + { + // + XPosition positions[]; + int positionsCount = mTrader + .GetInProfitPositions( + positions, + symbol, + provider, + period, + type, + method + // + ); + if (positionsCount <= 0) + { + return; + } + + // + string comment = "Close InProfit ..."; + mTrader.Close( + positions, + comment + // + ); + + // + string message = "Guard Close (" + ToString(positionsCount) + ") Postion(s) In Profit ..."; + + // + mAlert.Alert(message); + } + + // + // Close Max In Drawdown Trade Guard Action ... + void HandleGuardCloseInDrawdownAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method + ) + { + // + XPosition positions[]; + int positionsCount = mTrader + .GetInDrawdownPositions( + positions, + symbol, + provider, + period, + type, + method + // + ); + if (positionsCount <= 0) + { + return; + } + + // + string comment = "Close InDrawdown ..."; + mTrader.Close( + positions, + comment + // + ); + + // + string message = "Guard Close (" + ToString(positionsCount) + ") Position(s) In Drawdown ..."; + + // + mAlert.Alert(message); + } + + // + // Force Close Specified Set Of Position ... + void HandleGuardForceCloseAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ulong ticket = 0 // Specific Ticket + ) + { + // + string comment = ""; + + // + // Close All Positions ... + if (ticket == 0) + { + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions, + symbol, + provider, + period, + type + // + ); + if (positionsCount <= 0) + { + return; + } + + // + comment = provider + " Force Close Guard ..."; + + // + mTrader.Close( + positions, + comment + // + ); + } + // + // Close Specific Position ... + else + { + // + XPosition position; + bool hasPosition = mTrader + .GetPosition( + ticket, + position + // + ); + + // + if (hasPosition) + { + // + comment = provider + "(" + ToString(ticket) + ")" + " Force Close Guard ..."; + + // + mTrader.Close( + ticket, + comment + // + ); + } + } + + // + if (IsValid(comment)) + { + mAlert.Alert(comment); + } + } + + // + // Trailing Specified Set Of Positions Stop Losses ... + void HandleGuardTrailingStopAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double sl // Desired SL Value ... + ) + { + // + if (sl <= 0) + { + return; + } + + // + NormalizePrice( + sl, + symbol + // + ); + + // + XPosition positions[]; + int positionsCount = mTrader + .GetPositions( + positions, + symbol, + provider, + period, + type + // + ); + if (positionsCount <= 0) + { + return; + } + + // + int modified = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + string comment = PrepareSLTrailTag(iPosition.comment); + + // + if (iPosition.sl == sl) + { + continue; + } + + // + bool isModified = mTrader.Modify( + iPosition.ticket, + sl, + iPosition.tp, + comment); + if (isModified) + { + modified++; + } + } + + // + if (modified > 0) + { + // + string message = "(" + ToString(modified) + ") Position's Stop Trailed Successfully ..."; + + // + mAlert.Alert(message); + } + } + + // + // Add Support Signal for Specified Positions ... + void HandleGuardAddSupportPositionAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + // + XSignal support; + bool hasSupport = CheckForSupport( + support, + provider, + symbol, + type, + period + // + ); + + // + if (!hasSupport || !support.IsValid()) + { + return; + } + + // + // TODO: May be need to add Support Tag to comments ... + + // + ENUM_X_SIGNAL_EXECUTION_RESULT reason = NULL; + bool isExecuted = mTrader.ExecuteSignal( + support, + reason); + + // + string comment = NULL; + if (!isExecuted) + { + comment = "Support Execution Failed doue " + ToString(reason); + } + else + { + comment = "Guard Support Signal Executed Successfully ..."; + } + + // + if (IsValid(comment)) + { + mAlert.Alert(comment); + } + } + + // + // Cancel all Placed Orders ... + void HandleGuardCancelPendingOrdersAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + // + XOrder orders[]; + int ordersCount = mTrader.GetOrders( + orders, + symbol, + provider, + period, + ToOrderType(type), + ORDER_STATE_PLACED, + true // Filter by Magic ... + // + ); + if (ordersCount <= 0) + { + return; + } + + // + int canceledOrdersCount = mTrader.CancelOrders(orders); + + // + if (canceledOrdersCount > 0) + { + // + string message = "Guard Cancel (" + ToString(canceledOrdersCount) + ") Pending Orders ..."; + + // + mAlert.Alert(message); + } + } + + // + // Private ... +private: + // + // Props ... + + // + // Trade Class Instance ... + XSCTrade *mTrader; + XSCAlert *mAlert; + + // + // Check in Test Mode or not ... + bool mIsInTestMode; + + // + // Position Management ... + bool mAllowLong; // Allow Long Trades + bool mAllowShort; // Allow Short Trades + double mMinProfitPerTrade; // Min Profit Per Trade based On Volume Factor (Hedge) + double mMinProfitPerVolumeFactor; // Min Volume Factor for Calculating Profit (Hedge) + + // + // Event Handlers ... + TOnStopLoss mOnStopLossTriggered; + TOnTakeProfit mOnTakeProfitTriggered; + TOnDealsChanged mOnDealsChangedHandler; + TOnOrdersChanged mOnOrdersChangedHandler; + TOnPositionsChanged mOnPositionsChangedHandler; + TOnTradeStateChanged mOnTradeStateChangedHandler; +} + +// \ No newline at end of file diff --git a/Classes/x-saherelm.xhttp.class.mq5 b/Classes/x-saherelm.xhttp.class.mq5 new file mode 100644 index 00000000..82adadb6 --- /dev/null +++ b/Classes/x-saherelm.xhttp.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 XSCHttp : public XSCBase +{ + // + // Public ... +public: + // + // Constructor ... + void XSCHttp() + { + XSCHttp("", 10000); + } + void XSCHttp( + string path, // Base Folder to Store Data + int timeout // base timeout for Requests + ) + { + // + Path(path); + Timeout(timeout); + } + + // + // Deconstructor ... + void ~XSCHttp() + { + } + + // + // 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/Classes/x-saherelm.xtrade.class.mq5 b/Classes/x-saherelm.xtrade.class.mq5 index d83e326d..ff46fb12 100644 --- a/Classes/x-saherelm.xtrade.class.mq5 +++ b/Classes/x-saherelm.xtrade.class.mq5 @@ -994,7 +994,7 @@ public: // // Check Account Policy ... bool CheckAccountPolicy( - XSignal &mSignal, // For Executing Signal + XSignal &mSignal, // For Executing Signal ENUM_X_SIGNAL_EXECUTION_RESULT &state // State Holder ) { @@ -1078,7 +1078,7 @@ public: // // Execute a Signal ... bool ExecuteSignal( - XSignal &mSignal, // Signal + 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 diff --git a/Documents/x-test.x5ea.mq5 b/Documents/x-test.x5ea.mq5 index 3458e60c..3b22aa90 100644 --- a/Documents/x-test.x5ea.mq5 +++ b/Documents/x-test.x5ea.mq5 @@ -23,7 +23,6 @@ #define ShortName "X5EA" // -#include "../Libraries/x-saherelm.log.lib.mq5" #include "../Libraries/x-saherelm.draw.lib.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" #include "../Classes/x-saherelm.xtrade.class.mq5" @@ -70,7 +69,6 @@ int OnInit() } // - logTag = ShortName; drawPrefix = ShortName; // diff --git a/Experts/x-test.x5ea.mq5 b/Experts/x-test.x5ea.mq5 index 487a0d10..d4d28c69 100644 --- a/Experts/x-test.x5ea.mq5 +++ b/Experts/x-test.x5ea.mq5 @@ -23,7 +23,6 @@ #define ShortName "X5EA" // -#include "../Libraries/x-saherelm.log.lib.mq5" #include "../Classes/x-saherelm.x5.provider.class.mq5" // @@ -76,9 +75,6 @@ int OnInit() return INIT_PARAMETERS_INCORRECT; } - // - logTag = ShortName; - // // Initial Providers ... if (!InitialProviders()) diff --git a/Indicators/x-saherelm.xchlh.mq5 b/Indicators/x-saherelm.xchlh.mq5 index 8a1bef78..864b6335 100644 --- a/Indicators/x-saherelm.xchlh.mq5 +++ b/Indicators/x-saherelm.xchlh.mq5 @@ -107,10 +107,6 @@ input bool scDrawLL = true; // Draw Lowest Low // END Inputs ... // -// -// Includes Logging Library ... -#include "../Libraries/x-saherelm.log.lib.mq5"; - // // Includes Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5"; diff --git a/Indicators/x-saherelm.xmc.mq5 b/Indicators/x-saherelm.xmc.mq5 index ebcb8429..f7fe43bf 100644 --- a/Indicators/x-saherelm.xmc.mq5 +++ b/Indicators/x-saherelm.xmc.mq5 @@ -59,8 +59,8 @@ input ENUM_APPLIED_PRICE verifierMaAppliedTo = PRICE_CLOSE; // Applied To // input group "Presentation"; -input bool showFastMa = true; // Show Fast -input bool showSlowMa = true; // Show Slow +input bool showFastMa = true; // Show Fast +input bool showSlowMa = true; // Show Slow input bool showVerifierMa = true; // Show Verifier // @@ -71,10 +71,6 @@ input bool showVerifierMa = true; // Show Verifier // START Includes and Imports ... // -// -// Includes Logging Library ... -#include "../Libraries/x-saherelm.log.lib.mq5" - // // Includes Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5" @@ -169,9 +165,6 @@ int OnInit() return INIT_PARAMETERS_INCORRECT; } - // - logTag = ShortName; - // // because in some cases we may have more than one input for // calculation and we must prevent any calculation @@ -201,11 +194,6 @@ int OnInit() fastMaAppliedTo); if (fastMaHandler == INVALID_HANDLE) { - // - string msg = "Error in Initilizing Indicator ..."; - LogMessage(msg); - - // return INIT_FAILED; } @@ -220,11 +208,6 @@ int OnInit() slowMaAppliedTo); if (slowMaHandler == INVALID_HANDLE) { - // - string msg = "Error in Initilizing Indicator ..."; - LogMessage(msg); - - // return INIT_FAILED; } @@ -239,11 +222,6 @@ int OnInit() verifierMaAppliedTo); if (verifierMaHandler == INVALID_HANDLE) { - // - string msg = "Error in Initilizing Indicator ..."; - LogMessage(msg); - - // return INIT_FAILED; } @@ -332,7 +310,7 @@ int OnCalculate( int slowMaCalculatedBars = BarsCalculated(slowMaHandler); int verifierMaCalculatedBars = BarsCalculated(verifierMaHandler); if (fastMaCalculatedBars < maxLength || - slowMaCalculatedBars < maxLength || + slowMaCalculatedBars < maxLength || verifierMaCalculatedBars < maxLength) { return prev_calculated; @@ -348,8 +326,7 @@ int OnCalculate( int copiedVerifierMas = CopyBuffer(verifierMaHandler, 0, 0, limit, verifierMaBuffer); if (copiedFastMas <= 0 || copiedSlowMas <= 0 || - copiedVerifierMas <= 0 - ) + copiedVerifierMas <= 0) { return prev_calculated; } diff --git a/Libraries/x-saherelm.alert.lib.mq5 b/Libraries/x-saherelm.alert.lib.mq5 deleted file mode 100644 index 429d830e..00000000 --- a/Libraries/x-saherelm.alert.lib.mq5 +++ /dev/null @@ -1,187 +0,0 @@ -/////////////////////////////////////////////////////// -// -// SaherElm IT Center MQL5 Alert Library -// -------------------------------------- -// Name: XAlert -// Description: provides Alerts 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 - -// -// START Inputs ... -// -input group "Alerts"; -input bool enableAlerts = true; // Enable Alerts -input bool logAlerts = true; // Log Alerts -input bool terminalAlerts = false; // Terminal Alerts -input bool mailAlerts = false; // Mail Alerts -input bool pushAlerts = false; // Push Alerts -// -// END Inputs ... -// - -// -#include "x-saherelm.log.lib.mq5" - -// -// START Global Definitions: Variables, Properties and etc ... -// -string alertPrefix = "X-Alert"; -// -// END Global Definitions: Variables, Properties and etc ... -// - -// -// START Provided Functions ... -// -// -// Initial Library if required ... -bool OnInInitAlertLibrary() -{ - return false; -} - -// -// DeInitial Library if required ... -void OnDeinitAlertLibrary() -{ -} - -// -// Attach Alert Prefix to Message ... -string PrepareAlertMessage(string message) -{ - // - StringReplace(message, "\n", " | "); - - // - StringConcatenate(message, alertPrefix, " > ", message); - - // - return message; -} - -// -// Logging an Alert ... -void LogAlert(string message) -{ - // - // Validate Args ... - if (!enableAlerts || !logAlerts) - { - return; - } - - // - LogMessage(alertPrefix, message); -} - -// -// Terminal Alert ... -void TerminalAlert(string message) -{ - // - // Validate Args ... - if (!enableAlerts || !terminalAlerts) - { - return; - } - - // - // Prepare Message ... - message = PrepareAlertMessage(message); - - // Send Terminal Alert ... - Alert(message); -} - -// -// Mail Alert ... -void MailAlert(string message) -{ - // - // Validate Args ... - if (!enableAlerts || !mailAlerts) - { - return; - } - - // - // Send Mail Alert ... - SendMail(alertPrefix, message); -} - -// -// Send Push Notification ... -void PushAlert(string message) -{ - // - // Validate Args ... - if (!enableAlerts || !pushAlerts) - { - return; - } - - // - // Prepare Message ... - message = PrepareAlertMessage(message); - - // - // Send Push Notification Alert ... - SendNotification(message); -} - -// -// Alert Sending ... -void SendAlert(string message) -{ - // - // Validate Args ... - if (!enableAlerts) - { - return; - } - - // - // Log ... - if (logAlerts) - { - LogAlert(message); - } - - // - // Terminal ... - if (terminalAlerts) - { - TerminalAlert(message); - } - - // - // Mail ... - if (mailAlerts) - { - MailAlert(message); - } - - // - // Push ... - if (pushAlerts) - { - PushAlert(message); - } -} -// -// END Provided Functions ... -// diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index 9a1dcd9b..148d85fb 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -1023,8 +1023,8 @@ struct XOHCL // ENUM_SERIESMODE mMode = swing == X_SWING_HIGH - ? MODE_HIGH - : MODE_LOW; + ? MODE_HIGH + : MODE_LOW; // result = swing == X_SWING_HIGH @@ -1048,7 +1048,7 @@ struct XOHCL // // Find Lowest Bar Index ... int FindHighestIndex( - int mLength, // Loopback ... + int mLength, // Loopback ... ENUM_SERIESMODE mMode // Calculation mode ) { @@ -1082,7 +1082,7 @@ struct XOHCL // // Find Lowest ... double FindHighest( - int mLength, // Loopback ... + int mLength, // Loopback ... ENUM_SERIESMODE mMode // Calculation mode ) { @@ -1127,7 +1127,7 @@ struct XOHCL // // Find Lowest Bar Index ... int FindLowestIndex( - int mLength, // Loopback ... + int mLength, // Loopback ... ENUM_SERIESMODE mMode // Calculation mode ) { @@ -1161,7 +1161,7 @@ struct XOHCL // // Find Lowest ... double FindLowest( - int mLength, // Loopback ... + int mLength, // Loopback ... ENUM_SERIESMODE mMode // Calculation mode ) { @@ -3877,6 +3877,49 @@ string GetToken(T &item) return result; } +// +// Same as Get Token for Use in Classes ... +template +string GetSpecificToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + // // Generate Unique Tags ... template @@ -4855,14 +4898,14 @@ bool Contains( // result = queryIdx >= 0; - + // return result; } // bool Contains( - string &mQueries[], // Search Strings + string &mQueries[], // Search Strings string mContent, // Search Content bool ignoreCase = true // Ignore Case ) @@ -4874,29 +4917,32 @@ bool Contains( // Validate Queries ... int queriesCount = ArraySize(mQueries); result = queriesCount > 0; - if (!result) { + if (!result) + { return result; } // // Validate Content ... result = IsValid(mContent); - if (!result) { + if (!result) + { return result; } // int containsCount = 0; - for (int i = 0; i < queriesCount; i++) { + for (int i = 0; i < queriesCount; i++) + { // bool isContains = Contains( mQueries[i], mContent, - ignoreCase - ); + ignoreCase); // - if (!isContains) { + if (!isContains) + { // result = false; break; @@ -4908,7 +4954,7 @@ bool Contains( // result = containsCount == queriesCount; - + // return result; } diff --git a/Libraries/x-saherelm.http.lib.mq5 b/Libraries/x-saherelm.http.lib.mq5 deleted file mode 100644 index 97f7ac0a..00000000 --- a/Libraries/x-saherelm.http.lib.mq5 +++ /dev/null @@ -1,177 +0,0 @@ -/////////////////////////////////////////////////////// -// -// SaherElm IT Center MQL5 Http Library -// ------------------------------------------ -// Name: XHttp -// Description: provide http communication -// 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 - -// -// START Model Definition ... -// -enum X_HTTP_METHOD -{ - X_HTTP_GET, - X_HTTP_POST -}; -// -// END Model Definition ... -// - -// -// START Inputs ... -// -// -// END Inputs ... -// - -// -// START Global Definitions: Variables, Properties and etc ... -// -// -// END Global Definitions: Variables, Properties and etc ... -// - -// -// START Provided Functions ... -// -// -// Initial Library if required ... -bool OnInInitHttpLibrary() -{ - return false; -} - -// -// DeInitial Library if required ... -void OnDeinitHttpLibrary() -{ -} - -// -// 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; -} - -// -// 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; - } - - // - result = WebRequest( - strMethod, - url, - headers, - timeout, - payload, - response, - responseHeaders - ); - - // - 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; -} -// -// END Provided Functions ... -// diff --git a/Libraries/x-saherelm.log.lib.mq5 b/Libraries/x-saherelm.log.lib.mq5 deleted file mode 100644 index ad341253..00000000 --- a/Libraries/x-saherelm.log.lib.mq5 +++ /dev/null @@ -1,1084 +0,0 @@ -/////////////////////////////////////////////////////// -// -// SaherElm IT Center MQL5 Logger Library -// --------------------------------------- -// Name: XLogger -// Description: provides Logging 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 - -// -// START Inputs ... -// -// input group "Logging"; -// input bool enableLogging = true; // Enable Logging -bool enableLogging = true; // Enable Logging -// -// END Inputs ... -// - -// -// START Global Definitions: Variables, Properties and etc ... -// -string logTag = "X-Logger"; // LogTag -// -// END Global Definitions: Variables, Properties and etc ... -// - -// -// START Provided Functions ... -// -// -// Logging a Message ... -void LogMessage(string message) -{ - // - if (!enableLogging) - { - return; - } - - // - Print(logTag, " > ", message); -} -void LogMessage(string tag, string message) -{ - // - if (!enableLogging) - { - return; - } - - // - Print(tag, " > ", message); -} - -// -void LogEmptyLine() -{ - LogMessage(" "); -} - -// -void LogError( - int error = -1 // Specific Error -) { - // - if (error <= -1) { - error = GetLastError(); - } - - // - string errorMsg = GetErrorDescription(error); - - // - LogMessage("Error: " + errorMsg); -} - -// -// Logging an Array ... -void LogArray(int &array[]) -{ - // - if (!enableLogging) - { - return; - } - - // - Print(logTag, ">"); - ArrayPrint(array); -} -void LogArray(double &array[]) -{ - // - if (!enableLogging) - { - return; - } - - // - Print(logTag, ">"); - ArrayPrint(array); -} -void LogArray(string &array[]) -{ - // - if (!enableLogging) - { - return; - } - - // - Print(logTag, ">"); - ArrayPrint(array); -} -// -// END Provided Functions ... -// - - -// -// Error Descriptions Functions ... -// - -// -// 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; -} diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index 2d90d697..caead5c8 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -53,6 +53,9 @@ string XSymbolToken = "SMBL"; string XSupportToken = "SP"; string XEQMSupportToken = "EQM"; +// +string XSLTrailToken = "SLT"; + // string XActionToken = "A"; @@ -107,6 +110,19 @@ enum ENUM_X_SIGNAL_MANAGING_ACTIONS X_SIGNAL_PARTIAL_TRAIL, // Use 0 index as SL and Trail Stop on TP Levels and also Partial Close on TP Levels }; +// +// Available Guard Action ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_NOTHING, // Nothing + X_GUARD_ACTION_HEDGE, // Hedge + X_GUARD_PARTIAL_CLOSE, // Partial Close + X_GUARD_ACTION_TRAIL_STOP, // Trail StopLoss + X_GUARD_ACTION_FORCE_CLOSE, // Force Close + X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, // Add Support Signal + X_GUARD_ACTION_CANCEL_PENDING_ORDERS, // Cancel Pending Orders +}; + // // Structs ... @@ -2427,6 +2443,96 @@ struct XOnTradeHandlerState } }; +// +// Model Guard Info ... +struct XGuard +{ + // + string symbol; // Trading Symbol ... + string provider; // Signal Provider ... + ENUM_TIMEFRAMES period; // Trading Timeframe ... + ENUM_POSITION_TYPE type; // Position Type ... + ENUM_X_GUARD_ACTIONS action; // Which Action to Do ... + + // + double dblPayLoad; + string strPayload; + + // + // Constructor ... + XGuard() + { + Clean(); + } + + // + // Initialize ... + + // + // Global Initializer ... + bool Init( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... + ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... + ENUM_POSITION_TYPE mType = NULL, // Position Type ... + string mProvider = NULL, // Signal Provider ... + double mDblPayLoad = NULL, + string mStrPayload = NULL // + ) + { + // + type = mType; + symbol = mSymbol; + period = mPeriod; + action = mAction; + provider = mProvider; + dblPayLoad = mDblPayLoad; + strPayload = mStrPayload; + + // + bool result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + provider = NULL; + period = NULL; + action = X_GUARD_ACTION_NOTHING; + + // + strPayload = NULL; + dblPayLoad = EMPTY_VALUE; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + action != X_GUARD_ACTION_NOTHING + // + ; + + // + return result; + } +}; + // // Model a Position with all of it's Supports ... struct XPositionPack @@ -3717,6 +3823,73 @@ int FindIndex( return result; } +// +// Retrieve String Representation ... +string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SIGNAL_EXECUTION_UNKNOWN: + result = "Unknown"; + break; + + // + case X_SIGNAL_EXECUTION_SUCCEED: + result = "Succed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_SPREAD: + result = "Spread more than Max Allowed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_NO_EQUITY: + result = "No Equity for Trade"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR: + result = "Price Error"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: + result = "Max Allowed Positions Reached"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS: + result = "Invalid Params"; + break; + } + + // + return result; +} + +// +// Converts Position Type to Order Type ... +ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value) +{ + // + bool isLong = IsLong(value); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} + // // Tagging ... @@ -3830,3 +4003,96 @@ ulong ExtractEQMSupportedTicket(string value) } // +// 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; +} + +//