//////////////////////////////////////////////////////////// // // 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; XCReporter *xEU5Reporter; XCAccountInfo xEU5AccountInfo; // #include "x-saherelm.xeu5.provider.indicators.lib.mq5" // // Controlling Variables ... bool xEU5MEnableProvider = false; bool xEU5MAllowLongTrades = false; bool xEU5MAllowShortTrades = false; // double xEU5Deposit = 0; double xEU5Balance = 0; double xEU5MinReward = 0; double xEU5FreeMargin = 0; double xEU5StaticVolume = 0; double xEU5MaxAllowedVolume = 0; double xEU5BalanceForOpenTrades = 0; double xEU5FreeMarginForOpenTrades = 0; double xEU5ApplyVolumeMultiplierPrice = 0; // // TODO: Complete this ... // Buffer for Holding Max Volume and Max Drawdow ... double xEU5MaxDrawUp = 0; double xEU5MaxDrawDown = 0; datetime xEU5TradeTimes[]; double xEU5TradeVolumes[]; double xEU5TradeMaxDrawdowns[]; double xEU5TradeMaxAllowdVolumes[]; double xEU5MinBalanceForTradePrices[]; // int NOT_ENOUGH_MONEY_ERROR = 4756; const string XEU5_SUPPORT_ID = "SP"; // // 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; // if (!xEU5EnableProvider) { return result; } // // Controlling Variables ... xEU5MEnableProvider = xEU5EnableProvider; xEU5MAllowLongTrades = xEU5AllowLongTrades; xEU5MAllowShortTrades = xEU5AllowShortTrades; // // 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 Volume Multiplier Apply Grow Price ... if (xEU5ApplyVolumeMultiplierFactor > 0) { xEU5ApplyVolumeMultiplierPrice = xEU5Deposit * xEU5ApplyVolumeMultiplierFactor; } // XEU5CalculateStaticVolume(); XEU5CalculateMaxAllowedVolume(); // // Reset Calculations Buffers and Variables ... XEU5ResetCollectors(); // // Make XCTrader instance ... xEU5Trader = new XCTrade( XEU5ProviderName, _Symbol, xEU5Slippage, xEU5MagicNumber, xEU5MaxAllowedTrades, xEU5FreeMarginForOpenTrades, xEU5BalanceForOpenTrades); // // Retrieve an Instance of Reporter Class ... xEU5Reporter = new XCReporter(); xEU5Reporter.ResetReports(); XEU5UpdateReports(); // 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 (!xEU5MEnableProvider) { return; } // // Handling Signals ... XTraderHandlerResult handleSignalResult; xEU5Trader.HandleSignals( handleSignalResult, true, // Ignore Signal TP and SL for Virtal Handling false // Ignore Risk Free Trdaes ); // // Handle Sl Reports ... int handledSLsCount = ArraySize(handleSignalResult.sl); if (handledSLsCount > 0) { // for (int i = 0; i < handledSLsCount; i++) { xEU5Reporter.AddTradeSLInReports(); } } // // Handle TP Reports ... int handledTPsCount = ArraySize(handleSignalResult.tp); if (handledTPsCount > 0) { // for (int i = 0; i < handledTPsCount; i++) { xEU5Reporter.AddTradeTPInReports(); } } // // Handle RFs as TP Reports ... int handledRFsCount = ArraySize(handleSignalResult.rf); if (handledRFsCount > 0) { // for (int i = 0; i < handledRFsCount; i++) { xEU5Reporter.AddTradeSLInReports(); } } // // Update Account Info ... if ( handledSLsCount > 0 || handledTPsCount > 0 || handledRFsCount > 0) { XEU5UpdateReports(); } // // Reading Indicator Buffers ... XEU5HandleReadingBuffers(); if (xEU5CalculatedBars < xEU5MaxLengthOfInputs) { return; } // // Prepare and Update all required data ... double minBalanceForTradeBasedOnBalance = MathMax( xEU5BalanceForOpenTrades, xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor); xEU5Trader.SetMinBalanceForTradingPrice(minBalanceForTradeBasedOnBalance); if (xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor > xEU5BalanceForOpenTrades) { xEU5BalanceForOpenTrades = xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor; } // // Handle Open Trades ... XEU5HandleOpenTrades(); // // Handle Close Trades ... XEU5HandleCloseTrades(); // // Protect Account by Guarding Maximum Drawdown ... XEU5GuardAccount(); // // DrawDown and DrawUp ... XEU5HandleCalculateDrawDownUp(); } // // Handle Trades when OnTrade Event Hnadler Calls ... void XEU5SignalProviderHandleTrade() { // // Check Provider Enabled ... if (!xEU5MEnableProvider) { return; } // if (xEU5ScanStarted) { XEU5ProcessOnTradeContext(); } else { XEU5InitOnTradeContext(); } } // // Handle Open Trades ... void XEU5HandleOpenTrades() { // // Check Can Trade ... bool canTrade = xEU5MAllowLongTrades || xEU5MAllowShortTrades; 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; } // // Update Reports ... XEU5UpdateReports(); // // Open Long Trades ... if ( // hasLongSignal && xEU5MAllowLongTrades) { // bool isOpened = XEU5OpenLongPosition(longSignalInfo); } // // Open Short Trades ... if ( // hasShortSignal && xEU5MAllowShortTrades) { // 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 isClosedLongTrades = false; bool canCloseLongTrades = XEU5CanCloseLongTrade(); if (xEU5MAllowLongTrades && canCloseLongTrades) { // ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; // XSignal closed[]; xEU5Trader.CloseSignals( closed, type); // int closedTradesCount = ArraySize(closed); isClosedLongTrades = closedTradesCount > 0; if (isClosedLongTrades) { // XEU5IssueForceCloseTradesAlert(type); // for (int i = 0; i < closedTradesCount; i++) { xEU5Reporter.AddTradeSLInReports(); } } } // // Force Close Short Trades ... bool isClosedShortTrades = false; bool canCloseShortTrades = XEU5CanCloseShortTrade(); if (xEU5MAllowShortTrades && canCloseShortTrades) { // ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; // XSignal closed[]; xEU5Trader.CloseSignals( closed, type); // int closedTradesCount = ArraySize(closed); isClosedShortTrades = closedTradesCount > 0; if (isClosedShortTrades) { // XEU5IssueForceCloseTradesAlert(type); // for (int i = 0; i < closedTradesCount; i++) { xEU5Reporter.AddTradeSLInReports(); } } } // // Handle Actiong Long Time Trades ... XSignal longTimeHandleds[]; XEU5HandleLongTimeTrades(longTimeHandleds); int longTimeHandledsCount = ArraySize(longTimeHandleds); if (longTimeHandledsCount > 0) { // // Do What we want ... } // if (isClosedLongTrades || isClosedShortTrades) { XEU5UpdateReports(); } } // // 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; } // int signalsCount = xEU5Trader.Count(); bool isCross = signalsCount >= 1; if (isCross) { // // Handle Cross Signals ... XEU5HnadleCrossSignal(signal); } // // Retrieve Can Execute Signal or not ... bool canExecuteSignal = !isCross // || // ( // isCross && xEU5CrossSignalsMethod != XEU5_CROSS_SIGNAL_DO_NOTHING // ); if (!canExecuteSignal) { return result; } // // Execute Signal ... ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal( signal, false, // Ignore TP SL ... false, // Ignore Number of Trades ... true // Check Account Conditions ... ); result = executionResult == X_TRADER_SUCCEED_EXECUTION; if (result) { // XEU5IssueSignalExecutionAlert(signal); // // Update Reports ... string providers[]; for (int i = 0; i < ArraySize(info.signallers); i++) { // ENUM_XEU5_SIGNAL_PROVIDERS iProvider = info.signallers[i]; // Add( EnumToString(iProvider), providers); } xEU5Reporter.AddSignalToReports( signal, providers); } 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; } // int signalsCount = xEU5Trader.Count(); bool isCross = signalsCount >= 1; if (isCross) { // // Handle Cross Signals ... XEU5HnadleCrossSignal(signal); } // // Retrieve Can Execute Signal or not ... bool canExecuteSignal = !isCross // || // ( // isCross && xEU5CrossSignalsMethod != XEU5_CROSS_SIGNAL_DO_NOTHING // ); if (!canExecuteSignal) { return result; } // // Execute Signal ... ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal( signal, false, // Ignore TP SL ... false, // Ignore Number of Trades ... true // Check Account Conditions ... ); result = executionResult == X_TRADER_SUCCEED_EXECUTION; if (result) { // XEU5IssueSignalExecutionAlert(signal); // // Update Reports ... string providers[]; for (int i = 0; i < ArraySize(info.signallers); i++) { // ENUM_XEU5_SIGNAL_PROVIDERS iProvider = info.signallers[i]; // Add( EnumToString(iProvider), providers); } xEU5Reporter.AddSignalToReports( signal, providers); } else { XEU5IssueSignalExecutionError(executionResult); } // return result; } // // Apply Cross Signal Actions ... void XEU5HnadleCrossSignal( XSignal &signal // Specified Signal ... ) { // // Check Cross Signal Handling Enabled ... if (xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DO_NOTHING) { return; } // // First We have to Change Cross Signals Comment ... string comment = xEU5Trader.GenerateSignalComment( signal, true); // signal.comment = comment; // // If Every thing is Regular, prevent any changes here ... if (xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_REGULAR) { return; } // // Retrieve Max in Drawdown Signal ... XSignal maxInDDSignal = xEU5Trader.GetMaxInDrawdownSignal(); // // Validate Signal ... bool isValidSignal = maxInDDSignal.ticket > 0 && maxInDDSignal.symbol == signal.symbol && IsValid(maxInDDSignal, xEU5MagicNumber); if (!isValidSignal) { return; } // double volume = signal.volume; bool isDirectional = maxInDDSignal.type == signal.type; // // Prevent any changes on Regular Conditions ... bool isRegular = isDirectional ? ( // xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_REGULAR || xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT // ) : ( // xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_INDIRECTION_REGULAR || xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_IMPORTANT_INDIRECTION_REGULAR // ); if (isRegular) { return; } // // Important Act needs to Multiply volume by 2 ... volume *= 2; // // Set Volume of signal ... signal.volume = volume; } // // Long Time ( Too Old Trades ) Handling ... void XEU5HandleLongTimeTrades( XSignal &result[] // Holds Result ... ) { // CleanBuffer(result); // // Validate Args ... bool canHandle = xEU5MaxAllowedTrades > 0 && xEU5OldTradesAction != XEU5_TOO_OLD_IGNORE; if (!canHandle) { return; } // // Retrieve Old Trades ... XSignal signals[]; xEU5Trader.GetOldSignals( signals, xEU5MaxAllowedTradeAge, _Period); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // // Detect Which Value of Old Trade must be Closed ... double volumeMultiplier = 1; switch (xEU5OldTradesAction) { // case XEU5_TOO_OLD_CLOSE: case XEU5_TOO_OLD_CLOSE_IN_PROFIT: case XEU5_TOO_OLD_CLOSE_IN_DRAWDOWN: volumeMultiplier = 1; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_01: volumeMultiplier = 0.01; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_05: volumeMultiplier = 0.05; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_10: volumeMultiplier = 0.1; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_20: volumeMultiplier = 0.2; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_25: volumeMultiplier = 0.25; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_30: volumeMultiplier = 0.30; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_50: volumeMultiplier = 0.5; break; // case XEU5_TOO_OLD_PARTIAL_CLOSE_75: volumeMultiplier = 0.75; break; } // // Loop through Old Trades ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; double pCloseVolume = iSignal.volume * volumeMultiplier; pCloseVolume = NormalizeVolume(pCloseVolume, iSignal.symbol); // // Detect Completely Close Signal Or not ... if ( xEU5OldTradesAction == XEU5_TOO_OLD_CLOSE || (xEU5OldTradesAction == XEU5_TOO_OLD_CLOSE_IN_PROFIT && iSignal.profit > 0) || (xEU5OldTradesAction == XEU5_TOO_OLD_CLOSE_IN_DRAWDOWN && iSignal.profit < 0)) { // bool isClosed = xEU5Trader.Close( iSignal.ticket, xEU5Trader.GenerateSignalAgeComment(iSignal)); // if (isClosed) { Add( iSignal, result); } // continue; } // // Detect Signal Age ... int currentStep = xEU5MaxAllowedTradeAge; int nextStep = xEU5MaxAllowedTradeAge * 2; int signalAge = xEU5Trader.GetSignalAge(iSignal); if (signalAge >= currentStep && signalAge <= currentStep + 10) { // // Here we can apply First Partial Closing ... // bool isClosed = xEU5Trader.ClosePartial( iSignal.ticket, pCloseVolume, xEU5Trader.GenerateSignalAgeComment(iSignal)); // if (isClosed) { Add( iSignal, result); } } } } // // Handle Close Trades When Profits is Under Specified Price ... void XEU5GuardAccount() { // // Check Guard Enabled ... if (xEU5MaxAllowedRiskOnTradesFactor <= 0) { return; } // // Calculate Max Allowed Drawdown ... double xEU5MaxAllowedRiskOnTradesPrice = MathMax( xEU5BalanceForOpenTrades, xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor); // // Count Trades ... int signalsCount = xEU5Trader.Count(); if (signalsCount <= 0) { return; } // // Count Open Trades and Calculate Profits ... double profit = xEU5Trader.GetSignalsProfit(); // // Prevent Moving forward when trades on Profit ... if (profit >= 0) { return; } // // Make Profit Check ... bool isGuardAttacked = MathAbs(profit) >= xEU5MaxAllowedRiskOnTradesPrice; if (!isGuardAttacked) { return; } // string message = ""; // // Handle Perform Guard Action ... switch (xEU5GuardAction) { // // Close All ... case XEU5_GUARD_CLOSE_ALL: { // XSignal closed[]; xEU5Trader.CloseSignals(closed); int closedCount = ArraySize(closed); if (closedCount <= 0) { return; } // message = "Closed (" + (string)closedCount + ") Trades by Guard ..."; } break; // case XEU5_GUARD_CLOSE_MAX_IN_DD: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60: case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75: { // // Retrieve Max In Drawdown Trade ... XSignal maxInDDSignal = xEU5Trader.GetMaxInDrawdownSignal(); bool isValid = IsValid(maxInDDSignal, xEU5MagicNumber) && maxInDDSignal.ticket > 0; if (!isValid) { break; } // // Close Max In Drawdown Trade ... if (xEU5GuardAction == XEU5_GUARD_CLOSE_MAX_IN_DD) { // string comment = "Signal (" + (string)maxInDDSignal.ticket + ") Closed by Guard ..."; bool isClosed = xEU5Trader.Close( maxInDDSignal.ticket, comment); if (isClosed) { // message = comment; break; } // break; } // // Partial Close Max In Drawdown Trade ... double volumeRate = 0.5; if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5) { volumeRate = 0.05; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10) { volumeRate = 0.10; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25) { volumeRate = 0.25; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30) { volumeRate = 0.30; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40) { volumeRate = 0.40; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50) { volumeRate = 0.50; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60) { volumeRate = 0.60; } else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75) { volumeRate = 0.75; } // double volume = NormalizeVolume( maxInDDSignal.volume * volumeRate, maxInDDSignal.symbol); // string comment = "Signal (" + (string)maxInDDSignal.ticket + ") Partial Closed (" + (string)volumeRate + ") by Guard ..."; // bool isClosed = xEU5Trader.ClosePartial( maxInDDSignal.ticket, volume, comment); if (isClosed) { // message = comment; break; } } break; // // Nothing ... // Default ... default: message = "Max Allowed Drawdown Reached ..."; break; } // if (StringLen(message) <= 0) { return; } // XEU5IssueAlert(message); } // // Calculate Usefull data ... void XEU5HandleCalculateDrawDownUp() { // XSignal signals[]; xEU5Trader.GetSignals(signals); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // double profit = 0; double volume = 0; double maxAllowedVolume = xEU5MaxAllowedVolume; for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // profit += iSignal.profit; // volume = volume == 0 || volume < iSignal.volume ? iSignal.volume : volume; } // if (profit < 0) { // xEU5MaxDrawDown = xEU5MaxDrawDown == 0 || xEU5MaxDrawDown > MathAbs(profit) ? MathAbs(profit) : xEU5MaxDrawDown; // // Update Buffers ... datetime time = iTime(_Symbol, _Period, 0); // // Calculate Max Allowed Drawdown ... double xEU5MaxAllowedRiskOnTradesPrice = MathMax( xEU5BalanceForOpenTrades, xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor); // Add( time, xEU5TradeTimes); Add( volume, xEU5TradeVolumes); Add( xEU5MaxDrawDown, xEU5TradeMaxDrawdowns); Add( maxAllowedVolume, xEU5TradeMaxAllowdVolumes); Add( xEU5MaxAllowedRiskOnTradesPrice, xEU5MinBalanceForTradePrices); } else { // xEU5MaxDrawUp = xEU5MaxDrawUp == 0 || xEU5MaxDrawUp < profit ? profit : xEU5MaxDrawUp; } // // Update Reports ... xEU5Reporter.UpdateMaxDrawUpInReports(xEU5MaxDrawUp); xEU5Reporter.UpdateMaxDrawDownInReports(xEU5MaxDrawDown); xEU5Reporter.UpdateMaxSameTimeTradesInReports(signalsCount); } // // 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(XEU5ProviderName + "> 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(XEU5ProviderName + "> 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 ... // // Detected TP or SL ... XDeal last = xEU5Trader.GetLastDeal(); if (last.reason == DEAL_REASON_SL) { xEU5Reporter.AddTradeSLInReports(); } else if (last.reason == DEAL_REASON_TP) { xEU5Reporter.AddTradeTPInReports(); } // // 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 .. // // // START Volume Baseed Functions ... // // // Calculate Account Grow Rate ... double XEU5GetAccountGrowRate() { // double result = 0; // double balanceDiff = xEU5Balance - xEU5Deposit; result = balanceDiff / xEU5ApplyVolumeMultiplierPrice; // return result; } // // Calculate Base Volume Multiplier ... double XEU5GetBaseVolumeMultiplier() { // double result = xEU5VolumeMultiplier; if (result <= 0) { result = 1; } // double growRate = XEU5GetAccountGrowRate(); if (growRate > 1) { result *= growRate; } // else if (growRate > 0 && growRate < 1) // { // result = (1 + growRate); // } else { result = 1; } // return result; } // // Calculate Max Allowed Volume Per Trades ... void XEU5CalculateMaxAllowedVolume() { // double calculatedMaxAllowedVolume = 0; if (xEU5MaxSupportedVolumePerTradeFactor <= 0) { xEU5MaxAllowedVolume = 0; } // calculatedMaxAllowedVolume = xEU5Deposit * xEU5MaxSupportedVolumePerTradeFactor; // if (xEU5IncreasedMaxSupportedVolumeRate > 0) { // double balanceRate = MathRound(xEU5Balance / xEU5Deposit); if (balanceRate >= xEU5IncreasedMaxSupportedVolumeRate) { // double multiplier = MathRound(balanceRate / xEU5IncreasedMaxSupportedVolumeRate) + 1; // calculatedMaxAllowedVolume *= multiplier; } } // xEU5MaxAllowedVolume = xEU5MaxAllowedVolume == 0 || calculatedMaxAllowedVolume > xEU5MaxAllowedVolume ? calculatedMaxAllowedVolume : xEU5MaxAllowedVolume; // // Normalize ... if (xEU5MaxAllowedVolume > 0) { xEU5MaxAllowedVolume = NormalizeVolume(xEU5MaxAllowedVolume); } } // // Calculate Static Volume ... void XEU5CalculateStaticVolume() { // // Calculate Static Volume ... if (xEU5StaticVolumeMethod == XEU5_STATIC_VOLUME_BASED_ON_BALANCE) { xEU5StaticVolume = xEU5StaticVolumeFactor * xEU5Balance; } else { xEU5StaticVolume = xEU5StaticVolumeFactor * xEU5Deposit; } } // // 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 ... ) { // // Calculate Static Volume ... XEU5CalculateStaticVolume(); // 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 > 0) { // // Decrease Volume if Open Trades Exists ... double vDecreaseRate = openSignals + 1; // result /= vDecreaseRate; } // // Check Signal Max Allowed Volume ... XEU5CalculateMaxAllowedVolume(); double maxAllowedVolume = xEU5MaxAllowedVolume; if (maxAllowedVolume > 0) { // result = result < maxAllowedVolume ? result : maxAllowedVolume; } // // Normalize Volume ... result = NormalizeVolume(result); // return result; } // // END Volume Baseed Functions ... // // // START Reports Preparation Functions ... // // // Update Report Info ... void XEU5UpdateReports() { // XEU5CalculateStaticVolume(); XEU5CalculateMaxAllowedVolume(); double volumeMultiplier = xEU5VolumeMultiplier > 0 ? XEU5GetBaseVolumeMultiplier() : 1; // double staticVolume = xEU5StaticVolume; string staticVolumeCalculationMethod = EnumToString(xEU5StaticVolumeMethod); double maxAllowedVolume = xEU5MaxAllowedVolume; double volumeIncreaseMultiplier = volumeMultiplier; double balanceGowingToApplyMultiplier = xEU5ApplyVolumeMultiplierPrice; double balanceGrowingToIncreaseMaxAllowedVolume = xEU5Deposit * xEU5MaxSupportedVolumePerTradeFactor; // // Update Reports Volume Info ... xEU5Reporter.UpdateReportsVolumeInfo( staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); // // Calculate Max Allowed Drawdown ... double minBalanceForTradeBasedOnBalance = MathMax( xEU5BalanceForOpenTrades, xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor); xEU5Reporter.UpdateMinBalanceForOpenTradesInReports(minBalanceForTradeBasedOnBalance); } // // Reset XEU5 Info Buffers ... void XEU5ResetCollectors() { // // Reset Calculations Buffers and Variables ... xEU5MaxDrawUp = 0; xEU5MaxDrawDown = 0; CleanBuffer(xEU5TradeTimes); CleanBuffer(xEU5TradeVolumes); CleanBuffer(xEU5TradeMaxDrawdowns); CleanBuffer(xEU5TradeMaxAllowdVolumes); CleanBuffer(xEU5MinBalanceForTradePrices); } // // Generate Calculations Buffers and Variables Log String ... string XEU5GenerateCollectorString( int maxAvailable = 5 // Max Number of Parsing Buffers ... ) { // string result = ""; // // Validate ... int bufferSize = ArraySize(xEU5TradeTimes); if (bufferSize <= 0) { return result; } // result = "DD Info: \n"; // int logSize = MathMin(bufferSize, maxAvailable); for (int i = logSize - 1; i >= 0; i--) { // // Reading Requirement Buffers ... datetime iTime = xEU5TradeTimes[i]; double iVolume = xEU5TradeVolumes[i]; double iMaxDD = xEU5TradeMaxDrawdowns[i]; double iMaxAllowedVolume = xEU5TradeMaxAllowdVolumes[i]; double iMaxRiskableBalance = xEU5MinBalanceForTradePrices[i]; // // Generate Report ... result += (string)i + ":" + "\n"; result += "Time: " + (string)iTime + "\n"; result += "Volume: " + (string)iVolume + "\n"; result += "MaxDD: " + (string)iMaxDD + "\n"; result += "MaxAllowedVolume: " + (string)iMaxAllowedVolume + "\n"; result += "MaxRiskableBalance: " + (string)iMaxRiskableBalance + "\n"; } // return result; } // // END Reports Preparation Functions ... // // // START Alert Functions ... // 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 ) { // string message = xEU5Trader.ToString(signal); XEU5IssueAlert(message); } 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 = SignalToString(signal); XEU5IssueAlert(signalStr); } // // END Alert Functions ... // // // END Private Functions ... //