//////////////////////////////////////////////////////////// // // 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; // 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(); // // 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); // // TODO: Log it Later ... // // 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 openSignals = xEU5Trader.Count(); bool canOpenPositions = openSignals < 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.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); } } // XEU5HandleCloseInProfitTrades(); // XEU5HandleCloseMaxDrawDownTrades(); // XEU5HandleCloseTooOldTrades(); // XEU5CloseAllPositionsInPyramid(); } // // Handle Supported Trades ... void XEU5HandleSupportTrades() { // bool canDoTrade = xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0; if (!canDoTrade) { return; } // XEU5OpenSupportTrade(); } // // Handle Indirection Trades ... void XEU5HandleIndirectionTrades() { // if (!xEU5EnableIndirectionalSupportPositions) { return; } // // Retrieve Long Enuogh inDrawDown Trades ... // TODO: Complete this ... // int age = 5; // datetime time = iTime(_Symbol, _Period, 0); // // // XSignal oldTrades[]; // xEU5Trader.GetOldSignals( // oldTrades // age, // _Period, // X_SIGNAL_UNKNOWN); // 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 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(info.signalPusher); // 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( XEU5_SIGNAL &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(info.signalPusher); // 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; } // // Open a Support Signal ... void XEU5OpenSupportTrade() { // bool canDoTrade = xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0; if (!canDoTrade) { return; } // // Recieve InDD Open Trades ... // TODO: Complete this ... // 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; } // // TODO: Complete this ... // // // 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; // // TODO: Complete this ... // // // 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; } // // TODO: Complete this ... // // // 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() { // // TODO: Complete this ... // // // double profits = 0; // // // XSignal allPositions[]; // xEU5Trader.GetSignals(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.GetInProfitSignals(openInProfitTrades); int openTrades = ArraySize(openInProfitTrades); // // Calculate Normalized Multiplier ... double mVolumeMultiplier = xEU5VolumeMultiplier <= 0 ? 1 : xEU5VolumeMultiplier; double multiplier = mVolumeMultiplier; multiplier = multiplier; if (multiplier < 1) { multiplier = 1; } // double growRate = xEU5Balance / xEU5Deposit; if (growRate >= 1 && multiplier == 1) { // double growDiff = growRate - 1; if (growDiff < 1) { growRate = ((growDiff * 2) * 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 (openTrades > 0) { result /= openTrades + 1; } // 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 = {}; // // TODO: Complete this ... // // // // 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; // // TODO: Complete this ... // // // // 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 = {}; // // TODO: Complete this ... // // // // 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 ... //