//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XEU5 Signal Provider Library // -------------------------------------------------------- // Name: XEU5SignalProvider // Description: XEU5 based signal provider ... // // // 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 #define XEU5ProviderName "XEU5" // // START Inputs ... // #include "x-saherelm.xeu5.provider.inputs.lib.mq5"; // // END Inputs ... // // // Include Common Library ... #include "..\Libraries\x-saherelm.common.lib.mq5" // // Include Logger Library ... #include "..\Libraries\x-saherelm.log.lib.mq5" // // Include Alert Library ... #include "..\Libraries\x-saherelm.alert.lib.mq5" // // Include Draw Library ... #include "..\Libraries\x-saherelm.draw.lib.mq5" // // Include Class Libraries ... #include "..\Classes\x-saherelm.class.lib.mq5" // // START Global Definitions: Variables, Properties and etc ... // // XCTrade *xEU5Trader; XCAccountInfo xEU5AccountInfo; // #include "x-saherelm.xeu5.provider.indicators.lib.mq5" // double xEU5Deposit = 0; double xEU5Balance = 0; double xEU5MinReward = 0; double xEU5FreeMargin = 0; double xEU5BalanceForOpenTrades = 0; double xEU5FreeMarginForOpenTrades = 0; double xEU5BaseRiskableMoneyPerTrade = 0; double xEU5SupportTradesPriceDistance = 0; // int NOT_ENOUGH_MONEY_ERROR = 4756; // // On Trade Context Data ... // int xEU5DaysForRead = 1; // // set the limits of the trade history on the global scope ... datetime xEU5StartDate; // start date for trade history in cache datetime xEU5EndDate; // end date for trade history in cache // // global counters ... int xEU5Orders; // number of active orders int xEU5Positions; // number of open positions int xEU5Deals; // number of deals in the trade history cache int xEU5HistoryOrders; // number of orders in the trade history cache bool xEU5ScanStarted = false; // flag of counter relevance // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool XEU5InitSignalProviderLibrary() { // bool result = false; // // Reset On Trade Counter ... XEU5ResetOnTradeContext(); // // Init On Trade Context ... XEU5InitOnTradeContext(); // // Validate Inputs ... result = XEU5ValidateInputs(); if (!result) { return result; } // // Init Indicators ... result = XEU5InitIndicators(); if (!result) { return result; } // // Calculate Account Deposit ... xEU5Deposit = xEU5AccountInfo.GetInitialBalance(); // // Prepare Min Reward ... if (xEU5MinRewardInPips > 0) { xEU5MinReward = PipsToPrice(xEU5MinRewardInPips); } // // Calculate Min Balance for Trades ... if (xEU5BalanceFactorForOpenTrades > 0) { xEU5BalanceForOpenTrades = xEU5BalanceFactorForOpenTrades * xEU5Deposit; } // // Claculate Min Free Marging for Trades ... if (xEU5FreeMarginFactorForOpenTrades > 0) { xEU5FreeMarginForOpenTrades = xEU5FreeMarginFactorForOpenTrades * xEU5Deposit; } // // Calculate xEU5SupportTradesPriceDistance ... if (xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0) { xEU5SupportTradesPriceDistance = PipsToPrice(xEU5SupportTradesPriceDistanceInPips); } // // Calculate Base Riskable Money Per Trade ... if (xEU5MaxAllowedRiskPerTradesMultiplier > 0) { xEU5BaseRiskableMoneyPerTrade = (xEU5MaxAllowedRiskPerTradesMultiplier * xEU5Deposit); } // // Make XCTrader instance ... xEU5Trader = new XCTrade( XEU5ProviderName, _Symbol, xEU5Slippage, xEU5MagicNumber, xEU5MaxAllowedTrades, xEU5FreeMarginForOpenTrades, xEU5BalanceForOpenTrades); // result = true; // // Logging State ... XEU5IssueInitializationSucceedAlert(); // return result; } // // DeInitial Library if required ... void XEU5DeinitSignalProviderLibrary(const int reason) { // // Release Handlers ... XEU5ReleaseIndicators(); // // Logging State ... XEU5IssueDeinitializationSucceedAlert(); } // // this is a Globally Function which do all of // checkings and positions handling ... void XEU5SignalProviderHandleTick() { // // Update account Balance ... xEU5Balance = xEU5AccountInfo.GetBalance(); xEU5FreeMargin = xEU5AccountInfo.GetFreeMargin(); // // Check Provider is Enable or Not ... if (!xEU5EnableProvider) { return; } // // Handling Signals ... XTraderHandlerResult handleSignalResult; xEU5Trader.HandleSignals( handleSignalResult, true, // Ignore Signal TP and SL for Virtal Handling false // Ignore Risk Free Trdaes ); // // TODO: Log it Later ... // // Reading Indicator Buffers ... XEU5HandleReadingBuffers(); if (xEU5CalculatedBars < xEU5MaxLengthOfInputs) { return; } // // Handle Open Trades ... XEU5HandleOpenTrades(); // // Handle Close Trades ... XEU5HandleCloseTrades(); } // // Handle Trades when OnTrade Event Hnadler Calls ... void XEU5SignalProviderHandleTrade() { // if (xEU5ScanStarted) { XEU5ProcessOnTradeContext(); } else { XEU5InitOnTradeContext(); } } // // Handle Open Trades ... void XEU5HandleOpenTrades() { // // Check Can Trade ... bool canTrade = xEU5AllowLongTrades || xEU5AllowShortTrades; if (!canTrade) { return; } // // Check Max Open Trades ... int openSignals = xEU5Trader.Count(); bool canOpenPositions = openSignals < xEU5MaxAllowedTrades; if (!canOpenPositions) { return; } // // Check Signals Exists ... XEU5Signal longSignalInfo; XEU5Signal shortSignalInfo; bool hasLongSignal = XEU5CanOpenLongTrade(longSignalInfo); bool hasShortSignal = XEU5CanOpenShortTrade(shortSignalInfo); if (!hasLongSignal && !hasShortSignal) { return; } // // Open Long Trades ... if ( // hasLongSignal && xEU5AllowLongTrades) { // bool isOpened = XEU5OpenLongPosition(longSignalInfo); } // // Open Short Trades ... if ( // hasShortSignal && xEU5AllowShortTrades) { // bool isOpened = XEU5OpenShortPosition(shortSignalInfo); } } // // Handle Close Trades ... void XEU5HandleCloseTrades() { // // All Close Mechanism Handles Here ... // - Force Close; // - Partial Close; // - Risk Free Close; // - Virtual TP/SL Close; // // Force Close Long Trades ... bool canCloseLongTrades = XEU5CanCloseLongTrade(); if (xEU5AllowLongTrades && canCloseLongTrades) { // ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; // XSignal closed[]; xEU5Trader.CloseSignals( closed, type); // bool isClosed = ArraySize(closed) > 0; if (isClosed) { XEU5IssueForceCloseTradesAlert(type); } } // // Force Close Short Trades ... bool canCloseShortTrades = XEU5CanCloseShortTrade(); if (xEU5AllowShortTrades && canCloseShortTrades) { // ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; // XSignal closed[]; xEU5Trader.CloseSignals( closed, type); // bool isClosed = ArraySize(closed) > 0; if (isClosed) { XEU5IssueForceCloseTradesAlert(type); } } } // // Open Long Position ... bool XEU5OpenLongPosition( XEU5Signal &info // Retrieve Signal Additional Info on this Object ) { // bool result = false; // // Calculate Required Data for Position ... double entry = GetEntry(_Symbol, X_SIGNAL_LONG); double sl = info.sl > 0 ? info.sl : 0; double tp = info.tp > 0 ? info.tp : entry + xEU5MinReward; double riskFreeRate = xEU5RiskFreeRate; double riskFreeStep = xEU5RiskFreeStepInPips; double volume = XEU5CalculateVolume(ArraySize(info.signallers)); // XSignal signal = {}; signal = xEU5Trader.GenerateSignal( X_SIGNAL_LONG, tp, sl, volume, riskFreeStep, riskFreeRate); bool isValidSignal = IsValid( signal, xEU5MagicNumber); if (!isValidSignal) { return result; } // ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(signal); result = executionResult == X_TRADER_SUCCEED_EXECUTION; if (result) { XEU5IssueSignalExecutionAlert(signal); } else { XEU5IssueSignalExecutionError(executionResult); } // return result; } // // Open Short Position ... bool XEU5OpenShortPosition( XEU5Signal &info // Retrieve Signal Additional Info on this Object ) { // bool result = false; // // Calculate Required Data for Position ... double entry = GetEntry(_Symbol, X_SIGNAL_SHORT); double sl = info.sl > 0 ? info.sl : 0; double tp = info.tp > 0 ? info.tp : entry - xEU5MinReward; double riskFreeRate = xEU5RiskFreeRate; double riskFreeStep = xEU5RiskFreeStepInPips; double volume = XEU5CalculateVolume(ArraySize(info.signallers)); // XSignal signal = {}; signal = xEU5Trader.GenerateSignal( X_SIGNAL_SHORT, tp, sl, volume, riskFreeStep, riskFreeRate); bool isValidSignal = IsValid( signal, xEU5MagicNumber); if (!isValidSignal) { return result; } // ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(signal); result = executionResult == X_TRADER_SUCCEED_EXECUTION; if (result) { XEU5IssueSignalExecutionAlert(signal); } else { XEU5IssueSignalExecutionError(executionResult); } // return result; } // // END Provided Functions ... // // // START Private Functions ... // // // START On Trade Context Handler .. // // // Reset On Trade Scanner Context ... void XEU5ResetOnTradeContext() { // xEU5EndDate = TimeCurrent(); xEU5StartDate = xEU5EndDate - (xEU5DaysForRead * PeriodSeconds(PERIOD_D1)); } // // Initial Context Of Trade Scanner ... void XEU5InitOnTradeContext() { // ResetLastError(); // // load history ... bool selected = HistorySelect(xEU5StartDate, xEU5EndDate); if (!selected) { // LogMessage("XEU5 > Failed to Load OnTrade Context History ..."); // return; } // // get the current value ... xEU5Orders = OrdersTotal(); xEU5Positions = PositionsTotal(); xEU5Deals = HistoryDealsTotal(); xEU5HistoryOrders = HistoryOrdersTotal(); // xEU5ScanStarted = true; } // // Process On Trade Context ... void XEU5ProcessOnTradeContext() { // xEU5EndDate = TimeCurrent(); // ResetLastError(); // // download trading history from the specified interval to the program cache ... bool selected = HistorySelect(xEU5StartDate, xEU5EndDate); if (!selected) { // LogMessage("XEU5 > Failed to Load OnTrade Context History ..."); // return; } // // get the current values ... int currOrders = OrdersTotal(); int currPositions = PositionsTotal(); int currDeals = HistoryDealsTotal(); int currHistoryOrders = HistoryOrdersTotal(); // // Orders ... // check if the number of active orders has been changed ... if (currOrders != xEU5Orders) { // // number of active orders has been changed ... // // update the value ... xEU5Orders = currOrders; } // // Positions ... // changes in the number of open positions ... if (currPositions != xEU5Positions) { // // number of open positions has been changed ... // // update the value ... xEU5Positions = currPositions; } // // Deals ... // changes in the number of deals in the trade history cache ... if (currDeals != xEU5Deals) { // // number of deals in the trade history cache has been changed ... LogMessage("Handle New Deals: " + (string)TimeCurrent()); // // update the value ... xEU5Deals = currDeals; } // // History Orders ... // changes in the number of history orders in the trade history cache ... if (currHistoryOrders != xEU5HistoryOrders) { // // number of history orders in the trade history cache has been changed ... // // update the value ... xEU5HistoryOrders = currHistoryOrders; } // // checking if it is necessary to change the limits of the trade history to be requested in cache ... XEU5CheckStartDateInTradeHistory(); } // // Check Statrt Date In Trade History ... void XEU5CheckStartDateInTradeHistory() { // // initial interval, if we were to start working right now .. datetime currStart = TimeCurrent() - (xEU5DaysForRead * PeriodSeconds(PERIOD_D1)); // // make sure that the start limit of the trade history has not gone // more than 1 day over the intended date ... if (currStart - xEU5StartDate > PeriodSeconds(PERIOD_D1)) { // // correct the start date of history to be loaded in the cache ... xEU5StartDate = currStart; // // now reload the trade history for the updated interval ... HistorySelect(xEU5StartDate, xEU5EndDate); // //--- correct the deal and order counters in history for further comparison xEU5HistoryOrders = HistoryOrdersTotal(); xEU5Deals = HistoryDealsTotal(); } } // // END On Trade Context Handler .. // // // Calculate Account Grow Rate ... double XEU5GetAccountGrowRate() { // double result = 0; // result = xEU5Balance / xEU5Deposit; result = MathRound(result); // return result; } // // Calculate Base Volume Multiplier ... double XEU5GetBaseVolumeMultiplier() { // double result = xEU5VolumeMultiplier; if (result <= 0) { result = 1; } // double growRate = XEU5GetAccountGrowRate(); if (growRate > 1) { result *= growRate; } // return result; } // // Calculate Max Allowed Volume Per Trades ... double XEU5GetMaxAllowedVolume() { // double result = 0; // result = xEU5MaxSupportedVolumePerTradeInLots > 0 ? xEU5MaxSupportedVolumePerTradeInLots : 1; // double growRate = XEU5GetAccountGrowRate(); double growMultipier = xEU5VolumeMultiplier > 0 ? MathRound(growRate / (xEU5VolumeMultiplier * 3)) : 1; // if (growMultipier > 5) { growMultipier = 5; } // result *= growMultipier > 1 ? growMultipier : 1; // return result; } // // Calculating Volume for Tradings ... double XEU5CalculateVolume( double forceMultiplier = 0 // some times we get more than one signal at the same time, here we increase volume using this ... ) { // double result = xEU5StaticVolume; // double volumeMultiplier = xEU5VolumeMultiplier > 0 ? XEU5GetBaseVolumeMultiplier() : 1; volumeMultiplier = forceMultiplier > 0 ? volumeMultiplier * forceMultiplier : volumeMultiplier; // result *= volumeMultiplier; // // Check Open Trades ... int openSignals = xEU5Trader.Count(); if (openSignals > 1) { // // Decrease Volume if Open Trades Exists ... double vDecreaseRate = openSignals == 1 ? 2 : openSignals; // result /= vDecreaseRate; } // // Check Signal Max Allowed Volume ... double maxAllowedVolume = XEU5GetMaxAllowedVolume(); // result = result < maxAllowedVolume ? result : maxAllowedVolume; // // Normalize Volume ... result = NormalizeVolume(result); // return result; } void XEU5IssueInitializationSucceedAlert() { // string message = "Initializion of (" + XEU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; XEU5IssueAlert(message); } void XEU5IssueDeinitializationSucceedAlert() { // string message = "De Initializion of (" + XEU5ProviderName + " Provider" + ") Succeeded ..."; XEU5IssueAlert(message); } void XEU5IssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type) { // string typeStr = GetSignalType(type); if (StringLen(typeStr) == 0) { return; } // string message = "Force Close " + typeStr + " Trades ..."; XEU5IssueAlert(message); } void XEU5IssueMaxAllowedTradesReachedAlert() { // string message = "reached Max Allowed Same Time Trades ..."; XEU5IssueAlert(message); } void XEU5IssueMaxAllowedFreeMarginReachedAlert() { // string message = "reached FreeMarigin For Open Trades ..."; XEU5IssueAlert(message); } void XEU5IssueMinAllowedBalanceReachedAlert() { // string message = "doesn't have Minimum Balance For Open Trades ..."; XEU5IssueAlert(message); } void XEU5IssueSignalExecutionAlert( XSignal &signal // Executed Signal ) { // XEU5IssueAlert(signal); } void XEU5IssueSignalExecutionError(int error) { // string message = GetSignalExecutionError(error); if (StringLen(message) == 0) { return; } // XEU5IssueAlert(message); } void XEU5IssueRiskFreeTradesAlert() { // string message = "Make Some Trades Risk Free ..."; XEU5IssueAlert(message); } void XEU5IssueLongInProfitTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XEU5IssueAlert(message); } void XEU5IssueLongInDrawdownTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XEU5IssueAlert(message); } void XEU5IssueAlert(string message) { // if (xEU5EnableAlerts) { SendAlert(message); } else { LogMessage(message); } } void XEU5IssueAlert(XSignal &signal) { // string signalStr = xEU5Trader.ToString(signal); XEU5IssueAlert(signalStr); // // // if (xEU5EnableAlerts) // { // SendAlert(signal); // } // else // { // LogSignal(signal); // } } // // END Private Functions ... //