//////////////////////////////////////////////////////////// // // 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 "x-saherelm.common.lib.mq5" // // Include Logger Library ... #include "x-saherelm.log.lib.mq5" // // Include Alert Library ... #include "x-saherelm.alert.lib.mq5" // // Include Draw Library ... #include "x-saherelm.draw.lib.mq5" // // Include Class Libraries ... #include "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 xEU5FreeMargin = 0; double xEU5RiskFreeTrades = 0; double xEU5MinRewardPerTrade = 0; double xEU5BalanceForOpenTrades = 0; double xEU5FreeMarginForOpenTrades = 0; double xEU5BaseRiskableMoneyPerTrade = 0; double xEU5SupportTradesPriceDistance = 0; // int NOT_ENOUGH_MONEY_ERROR = 4756; // struct XEU5_INDIRECTION { datetime lastCheck; double profit; }; // struct XEU5_POSITION_HOLDING { ulong ticket; XEU5_INDIRECTION info[]; }; // XEU5_POSITION_HOLDING positionHoldings[]; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool XEU5InitSignalProviderLibrary() { // bool result = false; // // Validate Inputs ... result = XEU5ValidateInputs(); if (!result) { return result; } // // Init Indicators ... result = XEU5InitIndicators(); if (!result) { return result; } // // Calculate Account Deposit ... xEU5Deposit = xEU5AccountInfo.GetInitialBalance(); // // Calculate RiskFree Price Distance ... if (xEU5RiskFreeTradesInPips > 0 && xEU5RiskFreeRate > 0) { xEU5RiskFreeTrades = PipsToPrice(xEU5RiskFreeTradesInPips); } // // Calculate xEU5MinRewardPerTrade ... if (xEU5MinRewardPerTradeInPips > 0) { xEU5MinRewardPerTrade = PipsToPrice(xEU5MinRewardPerTradeInPips); } // // 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, xEU5MaxAllowedSupportTrades, xEU5MinRewardPerTradeInPips, xEU5SupportTradesPriceDistanceInPips, 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; } // // Reading Indicator Buffers ... XEU5HandleReadingBuffers(); if (xEU5CalculatedBars < xEU5MaxLengthOfInputs) { return; } // // Handle Open Trades ... XEU5HandleOpenTrades(); // // Handle Close Trades ... XEU5HandleCloseTrades(); // // Handle Support Trades ... // XEU5HandleSupportTrades(); // // Handle Indirection Trades ... // XEU5HandleIndirectionTrades(); } // // Handle Open Trades ... void XEU5HandleOpenTrades() { // // Check Can Trade ... bool canTrade = xEU5AllowLongTrades || xEU5AllowShortTrades; if (!canTrade) { return; } // // Check Max Open Trades ... int openPositions = xEU5Trader.Count(); int openTradeKinds = xEU5Trader.CountByKind( X_SIGNAL_UNKNOWN, X_KIND_TRADE); bool canOpenPositions = openTradeKinds < xEU5MaxAllowedTrades; if (!canOpenPositions) { return; } // // Check Signals Exists ... XEU5_SIGNAL longSignalInfo = {}; XEU5_SIGNAL 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.ClosePositionsByType( type, closed); // 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.ClosePositionsByType( type, closed); // bool isClosed = ArraySize(closed) > 0; if (isClosed) { XEU5IssueForceCloseTradesAlert(type); } } // // Close Risk Free Trades ... bool canRiskFree = xEU5RiskFreeTradesInPips > 0 && xEU5RiskFreeTrades > 0 && xEU5RiskFreeRate > 0; if (canRiskFree) { XSignal riskFrees[]; xEU5Trader.RiskFreeSignals(riskFrees); bool isRiskFree = ArraySize(riskFrees) > 0; if (isRiskFree) { XEU5IssueRiskFreeTradesAlert(); } } // XEU5HandleCloseInProfitTrades(); // XEU5HandleCloseMaxDrawDownTrades(); // XEU5HandleCloseTooOldTrades(); // XEU5CloseAllPositionsInPyramid(); } // // Handle Supported Trades ... void XEU5HandleSupportTrades() { // bool canDoTrade = xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0; if (!canDoTrade) { return; } // XEU5OpenSupportTrade(); } // // Handle Indirection Trades ... void XEU5HandleIndirectionTrades() { // // Retrieve Long Enuogh inDrawDown Trades ... int age = 5; datetime time = iTime(_Symbol, _Period, 0); // XSignal oldTrades[]; xEU5Trader.GetLongTimeTrades( age, _Period, X_SIGNAL_UNKNOWN, X_KIND_TRADE, oldTrades); int oldTradesCount = ArraySize(oldTrades); if (oldTradesCount > 0) { // // Loop Through Trades to Find In DrawDown Trades ... for (int i = 0; i < oldTradesCount; i++) { // XSignal iSignal = oldTrades[i]; // if (iSignal.profit >= 0) { continue; } // // // XEU5_INDIRECTION // XEU5_POSITION_HOLDING // // Check Position Exists Or not ... // If Exists => Update a tick ... // If not => Add new One ... int iSignalHoldingIndex = XEU5GetHoldingPositionIndex(iSignal.ticket); if (iSignalHoldingIndex >= 0) { // // Update Tick ... XEU5_INDIRECTION iInfo = {}; iInfo.lastCheck = time; iInfo.profit = iSignal.profit; // Add( iInfo, positionHoldings[iSignalHoldingIndex].info); } else { // // Add new ... XEU5_POSITION_HOLDING iHolding; iHolding.ticket = iSignal.ticket; // XEU5_INDIRECTION iInfo = {}; iInfo.lastCheck = time; iInfo.profit = iSignal.profit; // Add( iInfo, iHolding.info); // Add( iHolding, positionHoldings); } } } // int positionHoldingsCount = ArraySize(positionHoldings); if (positionHoldingsCount <= 0) { return; } // // Now Check List and Propose InDirection Trades ... for (int i = 0; i < positionHoldingsCount; i++) { // XEU5_POSITION_HOLDING iHolding = positionHoldings[i]; // int infoCount = ArraySize(iHolding.info); if (infoCount <= 0) { continue; } // bool isPriceDecreasing = IsDecreasing(0, infoCount - 1, iHolding); if (!isPriceDecreasing) { continue; } // // Retrieve Signal ... XSignal iParent = xEU5Trader.GetPosition(iHolding.ticket); // // Generate InDirection Signal ... XSignal iInDirectionSignal = XEU5GenerateInDirectionalSupportSignal(iParent); // // Execute Support Signal ... bool isExecuted = xEU5Trader.ForceExecuteSignal(iInDirectionSignal); if (isExecuted) { // // Issue Alert ... XEU5IssueAlert(iInDirectionSignal.comment); XEU5IssueSignalExecutionAlert(iInDirectionSignal); // // Cleanup iHolding Info ... ArrayFree(iHolding.info); ArrayResize(iHolding.info, 0); } } } // // Open Long Position ... bool XEU5OpenLongPosition( XEU5_SIGNAL &info // Retrieve Signal Additional Info on this Object ) { // bool result = false; // // Calculate Required Data for Position ... double sl = info.sl > 0 ? info.sl : 0; double tp = info.tp > 0 ? info.tp : xEU5MinRewardPerTrade; double riskFree = info.riskFree > 0 ? info.riskFree : xEU5RiskFreeTrades; double riskFreeRate = xEU5RiskFreeRate; double volume = XEU5CalculateVolume(info.signalPusher); // XSignal signal = {}; signal = xEU5Trader.GenerateTradeSignal( X_SIGNAL_LONG, tp, sl, volume, riskFree, riskFreeRate); bool isValidSignal = IsValid( signal, xEU5MagicNumber); if (!isValidSignal) { return result; } // int error = -1; result = xEU5Trader.ExecuteSignal(signal, error); if (result) { XEU5IssueSignalExecutionAlert(signal); } else { XEU5IssueSignalExecutionError(error); } // return result; } // // Open Short Position ... bool XEU5OpenShortPosition( XEU5_SIGNAL &info // Retrieve Signal Additional Info on this Object ) { // bool result = false; // // Calculate Required Data for Position ... double sl = info.sl > 0 ? info.sl : 0; double tp = info.tp > 0 ? info.tp : xEU5MinRewardPerTrade; double riskFree = info.riskFree > 0 ? info.riskFree : xEU5RiskFreeTrades; double riskFreeRate = xEU5RiskFreeRate; double volume = XEU5CalculateVolume(info.signalPusher); // XSignal signal = {}; signal = xEU5Trader.GenerateTradeSignal( X_SIGNAL_SHORT, tp, sl, volume, riskFree, riskFreeRate); bool isValidSignal = IsValid( signal, xEU5MagicNumber); if (!isValidSignal) { return result; } // int error = -1; result = xEU5Trader.ExecuteSignal(signal, error); if (result) { XEU5IssueSignalExecutionAlert(signal); } // return result; } // // Open a Support Signal ... void XEU5OpenSupportTrade() { // bool canDoTrade = xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0; if (!canDoTrade) { return; } // // Recieve InDD Open Trades ... XSignal inDDTrades[]; xEU5Trader.GetInDrawDownTrades( xEU5SupportTradesPriceDistance, X_SIGNAL_UNKNOWN, X_KIND_TRADE, inDDTrades); int inDDTradesCount = ArraySize(inDDTrades); if (inDDTradesCount <= 0) { return; } // // Loop through in DD Trades ... for (int i = 0; i < inDDTradesCount; i++) { // XSignal iSignal = inDDTrades[i]; // // Check Distance of Trades ... bool isDistancePassed = MathAbs(iSignal.profit) >= xEU5SupportTradesPriceDistance; if (!isDistancePassed) { continue; } // // Get Opened Support Trades for iSignal ... XSignal iSignalSupports[]; xEU5Trader.GetPositionsByKind( X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, iSignalSupports); int iSignalSupportsCount = ArraySize(iSignalSupports); if (iSignalSupportsCount > xEU5MaxAllowedSupportTrades) { continue; } // // Check Signal Exists or not ... XEU5_SIGNAL info = {}; bool hasSignal = iSignal.type == X_SIGNAL_LONG ? XEU5CanOpenLongTrade(info) : XEU5CanOpenShortTrade(info); if (!hasSignal) { continue; } // LogMessage("iSignal: " + (string)iSignal.ticket + "_" + GetSignalType(iSignal) + " passed Distance for Support: " + (string)iSignal.profit); LogMessage("iSignal Has Support Signal ..."); // // Generate Support Signal ... XSignal sSignal = GenerateSupportSignal( info.signalPusher, iSignal.type, iSignal); // int error = -1; bool isOpened = xEU5Trader.ExecuteSupportSignal( sSignal, error); if (isOpened) { XEU5IssueSignalExecutionAlert(sSignal); } else { XEU5IssueSignalExecutionError(error); } } } // // Close In Profit Trades ... // the senario is to close in profit trades // if they are old age ... // age calculated based on xEU5MaxInDrawDownTradeAge / 2 ... void XEU5HandleCloseInProfitTrades() { // // Validate Args ... if (xEU5MaxInProfitTradeAge <= 0) { return; } // int age = xEU5MaxInProfitTradeAge; double minProfit = 1; // XSignal oldTrades[]; xEU5Trader.GetLongTimeTrades( age, _Period, X_SIGNAL_UNKNOWN, X_KIND_TRADE, oldTrades); int oldTradesCount = ArraySize(oldTrades); for (int i = 0; i < oldTradesCount; i++) { // XSignal iTrade = oldTrades[i]; if (iTrade.profit > minProfit && iTrade.sl == 0) { // string comment = xEU5Trader.GetSignalForceClosedComment(iTrade); bool isClosed = xEU5Trader.Close( iTrade.ticket, comment); if (isClosed) { // // Issue Alert ... XEU5IssueAlert("Close In Profit Trade: (" + (string)iTrade.ticket + "), profit: " + (string)iTrade.profit); XEU5IssueAlert(comment); } } } // XSignal oldSupports[]; xEU5Trader.GetLongTimeTrades( age, _Period, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, oldSupports); int oldSupportsCount = ArraySize(oldSupports); for (int i = 0; i < oldSupportsCount; i++) { // XSignal iTrade = oldSupports[i]; if (iTrade.profit > minProfit && iTrade.sl == 0) { // string comment = xEU5Trader.GetSignalForceClosedComment(iTrade); bool isClosed = xEU5Trader.Close( iTrade.ticket, comment); if (isClosed) { // // Issue Alert ... XEU5IssueAlert("Close In Profit Trade: (" + (string)iTrade.ticket + "), profit: " + (string)iTrade.profit); XEU5IssueAlert(comment); } } } } // // Close All InDrawDown Trades ... void XEU5HandleCloseMaxDrawDownTrades() { // // Validate Args ... if (xEU5MaxAllowedRiskPerTradesMultiplier <= 0) { return; } // double baseRiskableMoney = xEU5BaseRiskableMoneyPerTrade > 0 ? xEU5BaseRiskableMoneyPerTrade : 1; // XSignal inDDTrades[]; xEU5Trader.GetInDrawDownTrades( 0, X_SIGNAL_UNKNOWN, X_KIND_TRADE, inDDTrades); // int inDDTradesCount = ArraySize(inDDTrades); if (inDDTradesCount > 0) { // // Loop through Trades ... for (int i = 0; i < inDDTradesCount; i++) { // XSignal iTrade = inDDTrades[i]; // // Calculate Max Allowed Risk Per iTrade ... double iMaxAllowedRisk = (iTrade.volume / xEU5StaticVolume) * baseRiskableMoney; // // Check Negative Profit Matchs Riskable Money ... bool isProfitPassed = MathAbs(iTrade.profit) >= iMaxAllowedRisk; if (isProfitPassed) { // string comment = xEU5Trader.GetSignalForceClosedComment(iTrade); // bool isClosed = xEU5Trader.Close(iTrade.ticket, comment); if (isClosed) { LogMessage("Signal: " + (string)iTrade.ticket + ", closed by: " + (string)iMaxAllowedRisk); XEU5IssueAlert(comment); } } } } // XSignal inDDSupports[]; xEU5Trader.GetInDrawDownTrades( 0, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, inDDSupports); // int inDDSupportsCount = ArraySize(inDDSupports); if (inDDSupportsCount > 0) { // // Loop through Trades ... for (int i = 0; i < inDDSupportsCount; i++) { // XSignal iTrade = inDDSupports[i]; // // Calculate Max Allowed Risk Per iTrade ... double iMaxAllowedRisk = (iTrade.volume / xEU5StaticVolume) * baseRiskableMoney; // // Check Negative Profit Matchs Riskable Money ... bool isProfitPassed = MathAbs(iTrade.profit) >= iMaxAllowedRisk; if (isProfitPassed) { // string comment = xEU5Trader.GetSignalForceClosedComment(iTrade); // bool isClosed = xEU5Trader.Close(iTrade.ticket, comment); if (isClosed) { XEU5IssueAlert(comment); } } } } } // // Close All Too Old Trades ... // the senario is to close all tardes which has long age ... // age calculated based on xEU5MaxInDrawDownTradeAge ... void XEU5HandleCloseTooOldTrades() { // // Validate Args ... if (xEU5MaxInDrawDownTradeAge <= 0) { return; } // XSignal oldTrades[]; xEU5Trader.GetLongTimeTrades( xEU5MaxInDrawDownTradeAge, _Period, X_SIGNAL_UNKNOWN, X_KIND_TRADE, oldTrades); int oldTradesCount = ArraySize(oldTrades); for (int i = 0; i < oldTradesCount; i++) { // XSignal iTrade = oldTrades[i]; if (iTrade.profit > 0) { continue; } // string comment = xEU5Trader.GetSignalLongTimeClosedComment(iTrade); bool isClosed = xEU5Trader.Close( iTrade.ticket, comment); if (isClosed) { // // Issue Alert ... XEU5IssueAlert("Signal (" + (string)iTrade.ticket + ") Closed because of Too Old Age, Profit: " + (string)iTrade.profit); XEU5IssueAlert(comment); } } // XSignal oldSupports[]; xEU5Trader.GetLongTimeTrades( xEU5MaxInDrawDownTradeAge, _Period, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, oldSupports); int oldSupportsCount = ArraySize(oldSupports); for (int i = 0; i < oldSupportsCount; i++) { // XSignal iTrade = oldSupports[i]; if (iTrade.profit > 0) { continue; } // string comment = xEU5Trader.GetSignalLongTimeClosedComment(iTrade); bool isClosed = xEU5Trader.Close( iTrade.ticket, comment); if (isClosed) { // // Issue Alert ... XEU5IssueAlert("Signal (" + (string)iTrade.ticket + ") Closed because of Too Old Age, Profit: " + (string)iTrade.profit); XEU5IssueAlert(comment); } } } // // Close All Positions if Balance in Profit ... void XEU5CloseAllPositionsInPyramid() { // double profits = 0; // XSignal allPositions[]; xEU5Trader.GetAllPositions(allPositions); int allPositionsCount = ArraySize(allPositions); if (allPositionsCount <= 1) { return; } // // Loop through Positions ... for (int i = 0; i < allPositionsCount; i++) { // XSignal iPosition = allPositions[i]; // profits += iPosition.profit; } // if (profits > 0) { // XSignal closed[]; xEU5Trader.CloseAllPositions(closed); int closedCount = ArraySize(closed); if (closedCount > 0) { // XEU5IssueAlert("Pyramid Closing (" + (string)closedCount + "), Profits: " + (string)profits + " ..."); // ArrayFree(positionHoldings); ArrayResize(positionHoldings, 0); } } } // // END Provided Functions ... // // // START Private Functions ... // // // 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 ... ) { // // Assign default Value ... double result = xEU5StaticVolume; // // we can count open trades and in draw down trades // then do check volume based on it for gridding ... XSignal openInProfitTrades[]; xEU5Trader.GetInProfitTrades( 0, X_SIGNAL_UNKNOWN, X_KIND_TRADE, openInProfitTrades); int openTrades = ArraySize(openInProfitTrades); // // Calculate Normalized Multiplier ... double mVolumeMultiplier = xEU5VolumeMultiplier <= 0 ? 1 : xEU5VolumeMultiplier; double multiplier = mVolumeMultiplier; multiplier = multiplier * openTrades; if (multiplier < 1) { multiplier = 1; } // double growRate = xEU5Balance / xEU5Deposit; if (growRate >= 1 && multiplier == 1) { // double growDiff = growRate - 1; if (growDiff < 1) { growRate = 1 + (growDiff * mVolumeMultiplier); } // multiplier = multiplier * growRate; } // result = multiplier * xEU5StaticVolume; // // Apply Force Multiplier ... if (forceMultiplier > 1) { result *= forceMultiplier; } // // Check Max Allowed Lottage ... double maxAllowedVolume = xEU5MaxSupportedVolumePerTradeInLots; if (growRate >= 4 * mVolumeMultiplier) { maxAllowedVolume *= mVolumeMultiplier; } // if ( maxAllowedVolume > 0 && result > maxAllowedVolume) { result = maxAllowedVolume; } // // Normalize Volume ... result = NormalizeVolume(result); // return result; } // // Generate Support Signal for Specific Trade ... XSignal GenerateSupportSignal( double forceVolumeMultiplier, // how many time increase volume based on signal providers ENUM_X_SIGNAL_TYPE type, // which type of support signal issued XSignal &parent // generate support signal for which Trade Kind Position ) { // XSignal result = {}; // // Validate Type ... bool isTypeValid = type == X_SIGNAL_LONG || type == X_SIGNAL_SHORT; if (!isTypeValid) { return result; } // // Validate Parent Signal ... bool isValidSignal = IsValid(parent, xEU5MagicNumber); if (!isValidSignal) { return result; } // // Validate Parent is Kind ... bool isKindValid = parent.kind == X_KIND_TRADE; if (!isKindValid) { return result; } // // Check Parent Ticket ... bool isValidTicket = parent.ticket > 0; if (!isValidTicket) { return result; } // // Validate DrawDown ... bool isInDD = parent.profit < 0; if (!isInDD) { return result; } // // Calculate What we Want ... // // RISKFREE ... double riskFreeRate = parent.riskFree; double riskFreePrice = parent.riskFreeRate; // // TP ... double tp = MathAbs(parent.tp); // // SL ... double sl = parent.sl; // // VOLUME ... int pOpenSupportCount = xEU5Trader.CountSupportedPositions(parent); double volume = parent.volume * forceVolumeMultiplier * xEU5VolumeMultiplier; // // Force to Increase Volume ... bool isEquityPassed = xEU5Trader.IsEquityReadyForTrade(); bool isFreeMarginPassed = xEU5Trader.IsFreeMarginReadyForTrade(); bool isBalancePassed = xEU5Trader.IsAccountBalanceReadyForTrade(); bool isVolumeOk = isEquityPassed && isFreeMarginPassed && isBalancePassed; if (!isVolumeOk) { // volume = NormalizeVolume(volume / 4); if (volume < xEU5StaticVolume) { volume = xEU5StaticVolume; } } // // Check and Normalize Volume based on MaxAllowed Volume ... if (xEU5MaxSupportedVolumePerTradeInLots > 0 && volume > xEU5MaxSupportedVolumePerTradeInLots) { volume = xEU5MaxSupportedVolumePerTradeInLots; } // // Normalize Volume ... volume = NormalizeVolume(volume); // // Generating Support Signal for Parent ... result = xEU5Trader.GenerateSupportSignal( type, tp, sl, volume, riskFreePrice, riskFreeRate, parent.ticket); // return result; } // // Check Parent Signal Has InDirectional Support Trade or not ... bool XEU5HasInDirectionalSupportTrade( XSignal &parent // generate support signal for which Trade Kind Position ) { // bool result = false; // // Validate Parent Signal ... bool isValidSignal = IsValid(parent, xEU5MagicNumber); if (!isValidSignal) { return result; } // ENUM_X_SIGNAL_TYPE inDirectionalSignalType = parent.type == X_SIGNAL_LONG ? X_SIGNAL_SHORT : X_SIGNAL_LONG; // string inDirectionalComment = xEU5Trader.GenerateInDirectionalSignalComment(parent); // XSignal allPositions[]; xEU5Trader.GetPositionsByKind( inDirectionalSignalType, X_KIND_TRADE, allPositions); int allPositionsCount = ArraySize(allPositions); if (allPositionsCount <= 0) { return result; } // // Loop Through Signals ... for (int i = 0; i < allPositionsCount; i++) { // XSignal iSignal = allPositions[i]; // // Check Conditions ... if (iSignal.comment == inDirectionalComment) { // result = true; break; } } // return result; } // // Generate InDirectional Support Signal ... XSignal XEU5GenerateInDirectionalSupportSignal( XSignal &parent // generate support signal for which Trade Kind Position ) { // XSignal result = {}; // // Validate Parent Signal ... bool isValidSignal = IsValid(parent, xEU5MagicNumber); if (!isValidSignal) { return result; } // // Check Signal Must be In DrawDown ... if (parent.profit > 0) { return result; } // ENUM_X_SIGNAL_TYPE type = parent.type == X_SIGNAL_LONG ? X_SIGNAL_SHORT : X_SIGNAL_LONG; bool isLong = type == X_SIGNAL_LONG; // string comment = xEU5Trader.GenerateInDirectionalSignalComment(parent); // // Check Has InDirectional Signal Or Not ... bool hasSupport = XEU5HasInDirectionalSupportTrade(parent); if (hasSupport) { return result; } // double reward = PipsToPrice(6); double riskFreeReward = PipsToPrice(3); double risk = GetSpread() * 2; // double inEntry = GetEntry(type); double inVolume = NormalizeVolume(parent.volume); double inSL = isLong ? inEntry - risk : inEntry + risk; double inTP = isLong ? inEntry + reward : inEntry - reward; double inRiskFree = isLong ? inEntry + riskFreeReward : inEntry - riskFreeReward; double inRiskFreeRate = 0.5; // // result = parent; result.sl = inSL; result.tp = inTP; result.type = type; result.entry = inEntry; result.volume = inVolume; result.comment = comment; result.riskFree = inRiskFree; result.riskFreeRate = inRiskFreeRate; // 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); // } } // // Retrieve Holding Position Index ... int XEU5GetHoldingPositionIndex(ulong ticket) { // int result = -1; // int total = ArraySize(positionHoldings); if ( total <= 0 || ticket <= 0) { return -1; } // for (int i = 0; i < total; i++) { // if (positionHoldings[i].ticket == ticket) { // result = i; break; } } // return result; } // void Add( XEU5_INDIRECTION &item, XEU5_INDIRECTION &buffer[]) { // ArrayResize( buffer, ArraySize(buffer) + 1); // buffer[ArraySize(buffer) - 1] = item; } // void Add( XEU5_POSITION_HOLDING &item, XEU5_POSITION_HOLDING &buffer[]) { // ArrayResize( buffer, ArraySize(buffer) + 1); // buffer[ArraySize(buffer) - 1] = item; } // // Check if a Value Decreasing in Loopback ... bool IsDecreasing( int from, // Last Time Index int to, // Fisr Tima Index XEU5_POSITION_HOLDING &holding // the position holding which required to search ) { // bool result = false; // double prices[]; for (int i = 0; i < ArraySize(holding.info); i++) { // XEU5_INDIRECTION info = holding.info[i]; // Add( info.profit, prices); } // ArraySetAsSeries(prices, true); // result = IsDecreasing( to, from, prices); // return result; } // // END Private Functions ... //