/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Expert Advisor // ---------------------------------------- // Name: XEA // Description: this is an expert controller // advisors which provides a mechanism for use them ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XEA EA" #property strict // // START Definitions ... // // string mProviderPrefix = "PRV"; string mSupportPrefix = "SP"; // enum ENUM_X_SIGNAL_PROVIDERS { NONE = 0, XICHI = 1, }; // // END Definitions ... // // // START Inputs ... // // // EA ... input group "Common"; input bool xEAEnable = true; // Enable EA input int xEASlippage = 10; // Slippgae input ulong xEAMagicNumber = 1604056; // Magic Number // // Determine Symbols and TimeFrames ... input group "Symbols and Time Frames"; // // (EURUSDb|M5|0.0005) // (EURUSDb|M5|0.0005)_(USDCHFb|M5|0.0005)_(USDJPYb|M5|0.0005)_(GBPUSDb|M5|0.0005) // (EURUSDb|M5,M15,M30|0.0005)_(USDCHFb|M5,M15|0.0005)_(USDJPYb|M5,M15|0.0005)_(GBPUSDb|M5,M15,M30|0.0005)_(AUDUSDb|M5,M15|0.0005)_(USDCADb|M5,M15|0.0005)_(NZDUSDb|M5,M15|0.0005)_(XAUUSDb|M5|0.0005) input string xEAProvidersDescription = "(EURUSDb|M5|0.0005)"; // Specify Symbols and Time Frames // // Signals ... input group "Signals"; input bool xEAEnableLongs = true; // Enable Long Trades input bool xEAEnableShorts = true; // Enable Short Trades // // Risk Management ... input group "Risk Management"; input int xEAMaxOpenPositions = 15; // Max Allowed Open Positions input bool xEABalancePositions = true; // Balance Positions input double xEAMaxAllowedDrawDownFactor = 0.15; // Max Allowed Drawdown Factor input int xEATrailStopsInPoint = 0; // Trail Stops Moving Rate in Points input int xEAMinProfitForHedging = 5; // Hedge Positions on Minimum Profit input double xEAMaxDrawdownForClosePosition = 0; // Max Drawdown For Close Positions input double xEAMaxDrawdownForSupportPosition = 0; // Max Drawdown For Open Support Positions // // Alerts ... input group "Alerts"; input bool xEAEnableAlerts = true; // Enable Events Alert input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month // // END Inputs ... // // // START Including Providers ... // // // Logger Library ... #include "../Libraries/x-saherelm.log.lib.mq5" // // Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5" // // Alert Library ... #include "../Libraries/x-saherelm.alert.lib.mq5" // // Draw Library ... #include "../Libraries/x-saherelm.draw.lib.mq5" // // Account Class ... #include "../Classes/x-saherelm.xaccount.class.mq5" // // Trade Class ... #include "../Classes/x-saherelm.xtrade.class.mq5" // // Signal Provider Class Library ... #include "../Providers/x.saherelm.x121.provider.mq5" // // END Including Providers ... // // // START Global Definitions: Variables, Properties and etc ... // // bool isXEANewHour; bool isXEANewDay; bool isXEANewWeek; bool isXEANewMonth; // // Determines EA is Running On Test Mode or not ... bool xEAIsTestMode = false; // // Check prevent Double Signalling on Same Candle ... bool xEAWaitUntilNextCandle = false; // XSCTrade *xEATrade; XSCAccount *xEAAccount; XLastSignal xEALastSignals[]; X121SignalProvider xEAProviders[]; // // END Global Definitions: Variables, Properties and etc ... // // // START Event Handlers ... // // // Initialization ... int OnInit() { // logTag = "XEA"; drawPrefix = logTag; alertPrefix = logTag; // // Reset Timings ... ResetTiming(); // // Validate Inputs ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // Initialize XEA Providers ... if (!InitializeProviders()) { return INIT_FAILED; } // // Initialize Trade Class ... xEATrade = new XSCTrade( xEASlippage, xEAMagicNumber); // // Initialize Account Class ... xEAAccount = new XSCAccount(); // // Init Succeed ... return INIT_SUCCEEDED; } // // DeInitialization ... void OnDeinit(const int reason) { // // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function // REASON_REMOVE 1 Program removed from a chart // REASON_RECOMPILE 2 Program recompiled // REASON_CHARTCHANGE 3 A symbol or a chart period is changed // REASON_CHARTCLOSE 4 Chart closed // REASON_PARAMETERS 5 Inputs changed by a user // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings // REASON_TEMPLATE 7 Another chart template applied // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed // // Here we can handle De Initialization Reasons ... delete xEATrade; delete xEAAccount; // // De Initialize XEA Providers ... } // // On Tick Handler ... void OnTick() { // // Handle Monthly Alert ... bool isFirstMonth = xMonth == -1; isXEANewMonth = IsNewMonth(); bool canMonthlyAlert = isXEANewMonth && xEAEnableAlerts && xEAEnableMonthlyAlerts; if (canMonthlyAlert) { // string message = "New Month ..."; // SendAlert(message); } // // Handle Weekly Alert ... bool isFirstWeek = xDayOfWeek == -1; isXEANewWeek = IsNewWeek(); bool canWeeklyAlert = isXEANewWeek && xEAEnableAlerts && xEAEnableWeeklyAlerts; if (canWeeklyAlert) { // string message = "New Week ..."; // SendAlert(message); } // // Handle Daily Alert ... bool isFirstDay = xDay == -1; isXEANewDay = IsNewDay(); bool canDailyAlert = isXEANewDay && xEAEnableAlerts && xEAEnableDailyAlerts; if (canDailyAlert) { // string message = "New Day ..."; // SendAlert(message); } // // Handle Hourly Alert ... bool isFirstHour = xHour == -1; isXEANewHour = IsNewHour(); bool canHourlyAlert = isXEANewHour && xEAEnableAlerts && xEAEnableHourlyAlerts; if (canHourlyAlert) { // string message = "New Hour ..."; // SendAlert(message); } // Guard(); // // Prevent Going Forward if user Disable it ... if (xEAEnable) { // // Call All Providers OnTick Method ... CallProvidersOnTick(); } } // // Handle Trade Events ... void OnTrade() { // // TODO: Complete this ... } // // END Event Handlers ... // // // START Functions ... // // // Validate Input Args for Initialization ... bool ValidateInputs() { // // TODO: Fix this ... bool result = true; // // Validate Args ... result = // xEASlippage > 0 && xEAMagicNumber > 0 && xEAMaxOpenPositions > 0 && xEAMaxAllowedDrawDownFactor > 0 && xEAMaxAllowedDrawDownFactor <= 0.4 && StringLen(xEAProvidersDescription) > 0 // ; // // Logging State ... string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; LogMessage(message); // return result; } // // Extract Signal Provider Struct from User Input ... bool InitializeProviders() { // bool result = false; // string workingString = xEAProvidersDescription; StringTrimLeft(workingString); StringTrimRight(workingString); if (StringLen(workingString) == 0) { return result; } // string descriptors[]; int numOfDescriptors = StringSplit( workingString, StringGetCharacter("_", 0), descriptors); if (numOfDescriptors <= 0) { return result; } // // Loop Through Descriptors ... for (int iDX = 0; iDX < numOfDescriptors; iDX++) { // string descriptor = descriptors[iDX]; // // Clear Start and End Pranteses ... StringReplace( descriptor, "(", ""); StringReplace( descriptor, ")", ""); // string descriptorData[]; int numOfData = StringSplit( descriptor, StringGetCharacter("|", 0), descriptorData); if (numOfData < 3) { continue; } // string symbols[]; int numOfSymbols = StringSplit( descriptorData[0], StringGetCharacter(",", 0), symbols); if (numOfSymbols <= 0) { continue; } // string timeFrames[]; int numOfTimeFrames = StringSplit( descriptorData[1], StringGetCharacter(",", 0), timeFrames); if (numOfTimeFrames <= 0) { continue; } // string riskAmounts[]; int numOfRiskAmounts = StringSplit( descriptorData[2], StringGetCharacter(",", 0), riskAmounts); if (numOfRiskAmounts <= 0) { continue; } // for (int cpIdx = 0; cpIdx < numOfSymbols; cpIdx++) { // string symbol = symbols[cpIdx]; // for (int tfIdx = 0; tfIdx < numOfTimeFrames; tfIdx++) { // string timeFrame = timeFrames[tfIdx]; ENUM_TIMEFRAMES period = ToPeriod(timeFrame); // double riskAmount = (double)(numOfRiskAmounts == numOfTimeFrames ? riskAmounts[tfIdx] : riskAmounts[0]); // string magicNumberString = "169" + (string)iDX + (string)cpIdx + (string)tfIdx + (string)PeriodSeconds(period) + "4056"; ulong magicNumber = (ulong)magicNumberString; // X121SignalProvider providerDescriptor; // providerDescriptor.symbol = symbol; providerDescriptor.period = period; providerDescriptor.riskAmount = riskAmount; providerDescriptor.magicNumber = magicNumber; // // Initial Provider Class Instance ... XSCX121Provider *x121Provider = new XSCX121Provider( symbol, period); // // Attach On Signal Event Listener ... x121Provider.AddOnSignalEventHandler(OnSignalRecieved); // providerDescriptor.provider = x121Provider; // Add( providerDescriptor, xEAProviders); } } } // result = true; // return result; } // void CallProvidersOnTick() { // int providersCount = ArraySize(xEAProviders); if (providersCount <= 0) { return; } // // Loop Through Providers ... for (int i = 0; i < providersCount; i++) { // X121SignalProvider providerDescriptor = xEAProviders[i]; // providerDescriptor.provider.OnTick(); } } // void OnSignalRecieved( XSignalInfo &info) { // // Ignore Disabled Signals ... if ((info.type == POSITION_TYPE_BUY && !xEAEnableLongs) || (info.type == POSITION_TYPE_SELL && !xEAEnableShorts)) { return; } // // Find Provider based On Signal Info ... int providersCount = ArraySize(xEAProviders); if (providersCount <= 0) { return; } // if (StringLen(info.symbol) == 0 || info.period == NULL) { return; } // bool isFoundDescriptor = false; X121SignalProvider providerDescriptor; // for (int i = 0; i < providersCount; i++) { // X121SignalProvider provDesc = xEAProviders[i]; // if (provDesc.symbol == info.symbol && provDesc.period == info.period) { // isFoundDescriptor = true; providerDescriptor = provDesc; // break; } } // // Prevent Moving Forward if there is no Descriptor Found ... if (!isFoundDescriptor) { return; } // // Count Open Positions ... int openPositionsCount = xEATrade.OpenPositionsCount(); // if (xEABalancePositions) { // // Count Same Signals for Balancing ... int smaeTypeOpenPositionsCount = xEATrade.OpenPositionsCount("", info.type); // if (openPositionsCount > (int)xEAMaxOpenPositions / 3) { // if (smaeTypeOpenPositionsCount > (int)openPositionsCount / 2) { return; } } } // string mTagId = GenerateTag(info); // // Check Last Signal ... datetime barTime = iTime( info.symbol, info.period, 0); // XLastSignal lastSignal = {}; int foundedLastSignalId = -1; bool isFoundLastSignal = false; int lastSignalsCount = ArraySize(xEALastSignals); // for (int i = 0; i < lastSignalsCount; i++) { // XLastSignal mLS = xEALastSignals[i]; if (mLS.provider == mTagId) { // lastSignal = mLS; foundedLastSignalId = i; isFoundLastSignal = true; // break; } } // if (isFoundLastSignal) { // bool isSameDate = xEALastSignals[foundedLastSignalId].at == barTime; if (isSameDate) { return; } else { xEALastSignals[foundedLastSignalId].at = barTime; } } else { // lastSignal.at = barTime; lastSignal.provider = mTagId; // ArrayResize( xEALastSignals, ArraySize(xEALastSignals) + 1); // xEALastSignals[ArraySize(xEALastSignals) - 1] = lastSignal; } // // Retrieve Tradable Balance ... double availableBalance = xEAAccount.GetEquity(); // // Here we Have to Check Some Conditions for Open // Positions, before Do Calculations, for improve Performance ... // // Verify Open Positions ... if (openPositionsCount >= xEAMaxOpenPositions) { // LogMessage("Max Allowed Positions Reached ..."); return; } // // Verify Available Balance ... double balance = xEAAccount.GetBalance(); double minBalanceForTrades = balance * xEAMaxAllowedDrawDownFactor; if (availableBalance <= minBalanceForTrades) { // LogMessage("Max Drawdown Reached ..."); return; } // // Here i Must Calculate TP and SL based on R2R and riskable Factor ... bool isLong = IsLong(info.type); // // Correct Period ... if (info.period == NULL) { info.period = providerDescriptor.period; } // // Check Order Mode ... if (info.mode == NULL) { // // Set Market Execution as Default ... info.mode = X_ORDER_MODE_MARKET; } // // Calculate Entry Price ... if (info.entry <= 0) { // info.entry = GetEntry( info.symbol, info.type); } // // R2R ... if (info.r2r <= 0) { // // Set Default Risk to Reward Ratio to 1 ... info.r2r = 1; } // // Set Risk Amount Factor ... if (info.riskAmount <= 0) { // info.riskAmount = providerDescriptor.riskAmount; } // // Calculate TP and SL ... double mPoint = GetPoints(info.symbol); // // Normalize SL Price ... if (info.sl > 0) { info.sl = NormalizePrice(info.sl, info.symbol); } // // Retrieve Symbol Point Value ... double pointValue = xEAAccount.GetPointValue(info.symbol); // // Calculate Risk ... double riskPrice = MathAbs(info.entry - info.sl); riskPrice = NormalizePrice(riskPrice, info.symbol); // double riskPoints = PriceToPoint(riskPrice); riskPoints = NormalizeDouble(riskPoints, 0); // // Calculating Reward based On Ratio ... double rewardPoints = riskPoints * info.r2r; double rewardPrice = PointToPrice(rewardPoints); rewardPrice = NormalizePrice(rewardPrice, info.symbol); // // TODO: Remove This ... // rewardPrice = PipsToPrice( // info.symbol, // 15 // ); // // Calculate TP Price ... double tpValue = isLong ? info.entry + rewardPrice : info.entry - rewardPrice; // // Calculate SL Price ... double slValue = isLong ? info.entry - riskPrice : info.entry + riskPrice; // // Balance Amount which we risks on each Provider's Trade ... double amount = availableBalance * info.riskAmount; // // Calculating Trade Volume based on risk Points and Amount ... double volume = xEAAccount.CalculateVolume( info.symbol, amount, riskPoints); volume = NormalizeVolume(volume, info.symbol); // // Set Caculated TP, SL and Volume ... info.tp = tpValue; info.sl = slValue; info.volume = 0.01; // volume; // string comment = ""; int signalProvidersCount = ArraySize(info.providers); if (signalProvidersCount > 0) { // string prvs = ""; for (int i = 0; i < signalProvidersCount; i++) { // string p = info.providers[i]; // if (StringLen(prvs) > 0) { prvs += ","; } // prvs += p; } // comment = "PRV(" + prvs + ")"; } // bool isPositionOpen = false; // // Open Signal Position ... if (isLong) { // isPositionOpen = xEATrade.Buy( info.symbol, info.period, info.volume, info.entry, info.sl, info.tp, comment); } else { // isPositionOpen = xEATrade.Sell( info.symbol, info.period, info.volume, info.entry, info.sl, info.tp, comment); } // if (isPositionOpen) { // // Retrieve Position Ticket ... ulong ticket = xEATrade.GetLastOpenPositionTicket(); if (ticket == 0) { return; } // // Draw Signal ... ReDrawSignal(ticket, info); // // Alert Position ... LogMessage("Position: " + (string)ticket + " was Open ..."); } } // // Do Guard Actions ... void Guard() { // // Close Max In Drawdown Position ... HandleMaxDrawdown(); // // Trailing Stops ... HandleTrailing(); // // Close All Open Positions in Pyramid ... HandleHedging(); // // Handle Support Signal Opening ... HandleSupport(); } // // it is a way to Protect Open Signal ... void HandleTrailing() { // if (xEATrailStopsInPoint <= 0) { return; } // XPosition inProfitPositions[]; xEATrade.GetInProfitPositions(inProfitPositions); int inProfitPositionsCount = ArraySize(inProfitPositions); if (inProfitPositionsCount <= 0) { return; } // for (int i = 0; i < inProfitPositionsCount; i++) { // XPosition iPosition = inProfitPositions[i]; // bool isLong = IsLong(iPosition.type); // // Retrieve Exit Price ... double exitPrice = GetExit( iPosition.symbol, iPosition.type); // double entryPrice = GetEntry( iPosition.symbol, iPosition.type); // // Calculate Price Distance ... double distancePrice = iPosition.sl == 0 ? MathAbs(iPosition.entry - exitPrice) : MathAbs(iPosition.sl - exitPrice); double distancePoint = PriceToPoint( iPosition.symbol, distancePrice); // if (distancePoint >= xEATrailStopsInPoint) { // double trailStepPrice = PointToPrice( iPosition.symbol, xEATrailStopsInPoint); // double tp = isLong ? iPosition.tp + trailStepPrice : iPosition.tp - trailStepPrice; double sl = iPosition.sl == 0 ? isLong ? entryPrice - trailStepPrice : entryPrice + trailStepPrice : isLong ? iPosition.sl + trailStepPrice : iPosition.sl - trailStepPrice; // bool isModified = xEATrade.Modify( iPosition.ticket, sl, tp); if (isModified) { // // Convert Position to Signal ... // XSignalInfo signal = ToSignalInfo(iPosition); // ReDrawSignal(iPosition.ticket, signal); // // Alert Trailing ... LogMessage("Position: " + (string)iPosition.ticket + ", was Trailed ..."); } } } } // // Hedging Close Positions ... void HandleHedging() { // if (xEAMinProfitForHedging <= 0) { return; } // int positionsCount = xEATrade.OpenPositionsCount(); if (positionsCount <= 1) { return; } // double profit = xEATrade.GetPositionsProfit(); // if (profit < xEAMinProfitForHedging) { return; } // string comment = "Hedging Pyramid ..."; // xEATrade.CloseAllPositions(comment); } // // Support Positions ... void HandleSupport() { // if (xEAMaxDrawdownForSupportPosition <= 0) { return; } // int positionsCount = xEATrade.OpenPositionsCount(); if (positionsCount <= 0) { return; } // XPosition inDrawdownPositions[]; xEATrade.GetInDrawdownPositions(inDrawdownPositions); int inDrawdownPositionsCount = ArraySize(inDrawdownPositions); if (inDrawdownPositionsCount <= 0) { return; } // for (int i = 0; i < inDrawdownPositionsCount; i++) { // XPosition iPosition = inDrawdownPositions[i]; // if (MathAbs(iPosition.profit) >= xEAMaxDrawdownForSupportPosition) { // // Here we have to Open Support Indirectional Position ... OpenSupportPosition(iPosition); } } } // // Close Max In Drawdown Position ... void HandleMaxDrawdown() { // if (xEAMaxDrawdownForClosePosition <= 0) { return; } // int positionsCount = xEATrade.OpenPositionsCount(); if (positionsCount <= 0) { return; } // XPosition inDrawdownPositions[]; xEATrade.GetInDrawdownPositions(inDrawdownPositions); int inDrawdownPositionsCount = ArraySize(inDrawdownPositions); if (inDrawdownPositionsCount <= 0) { return; } // for (int i = 0; i < inDrawdownPositionsCount; i++) { // XPosition iPosition = inDrawdownPositions[i]; // if (MathAbs(iPosition.profit) >= xEAMaxDrawdownForClosePosition) { // // Here we have to Force Close Position ... string comment = "Close On Guard ..."; bool isClosed = xEATrade.Close( iPosition.ticket, comment); if (isClosed) { LogMessage("Position: " + (string)iPosition.ticket + " was Closed On Guard ..."); } } } } // // Draw Signal ... void ReDrawSignal(const ulong ticket, XSignalInfo &signal) { // return; // bool isLong = IsLong(signal.type); // string prefix = (string)ticket + "_" + ToString(signal.period); // RemoveDraws(prefix); // // Retrieve Time ... datetime time = iTime( signal.symbol, signal.period, 0); // // Retrieve 3 Time ... datetime time3 = iTime( signal.symbol, signal.period, 3); // color posColor = isLong ? clrAqua : clrMagenta; color tpColor = clrAqua; color slColor = clrMagenta; color entryColor = clrGold; // ENUM_LINE_STYLE vLineStyle = STYLE_DOT; ENUM_LINE_STYLE tpLineStyle = STYLE_SOLID; ENUM_LINE_STYLE slLineStyle = STYLE_SOLID; ENUM_LINE_STYLE entryLineStyle = STYLE_SOLID; // long chartID = ChartID(); // // Vertical Line ... string vlName = prefix + "_" + (string)time; // DrawVerticalLine( chartID, vlName, 0, time, posColor, vLineStyle); // // TP ... double profit = (MathAbs(signal.tp - signal.entry)) * signal.volume; string tpName = prefix + "_TP_" + (string)profit; // DrawTrendLine( chartID, tpName, 0, time3, signal.tp, time, signal.tp, tpColor, tpLineStyle); // // SL ... double lost = (MathAbs(signal.sl - signal.entry)) * signal.volume; string slName = prefix + "_SL_" + (string)lost; // DrawTrendLine( chartID, slName, 0, time3, signal.sl, time, signal.sl, slColor, slLineStyle); // // ENTRY ... string entryName = prefix + "_ENTRY_" + (string)lost; // DrawTrendLine( chartID, entryName, 0, time3, signal.entry, time, signal.entry, entryColor, entryLineStyle); } // // Convert Position to Signal ... XSignalInfo ToSignalInfo( XPosition &position) { // XSignalInfo result; // result.tp = position.tp; result.sl = position.sl; result.type = position.type; result.entry = position.entry; result.symbol = position.symbol; result.period = position.period; result.volume = position.volume; // return result; } // string ToString(ENUM_X_SIGNAL_PROVIDERS provider) { // return EnumToString(provider); } // ENUM_X_SIGNAL_PROVIDERS ToProvider(string provider) { // ENUM_X_SIGNAL_PROVIDERS result; // if (ToString(XICHI) == provider) { result = XICHI; } else { result = NONE; } // return result; } // // Extract Position Provider ... ENUM_X_SIGNAL_PROVIDERS ExtractProviderFromComment(string comment) { // ENUM_X_SIGNAL_PROVIDERS result = NONE; // if (StringLen(comment) <= 0) { return result; } // string providerStr = ExtractString( comment, mProviderPrefix + "(", ")"); if (StringLen(providerStr) <= 0) { return result; } // result = ToProvider(providerStr); // return result; } // // Retrieve Specific Type of Providers Positions ... void GetSpecificProviderPositions( XPosition &result[], // Holds Result string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period ENUM_X_SIGNAL_PROVIDERS provider // Position Provider ) { // Clear(result); // if (StringLen(symbol) == 0 || provider == NONE) { return; } // int positionsCount = xEATrade.OpenPositionsCount(); if (positionsCount <= 0) { return; } // XPosition symbolPeriodPositions[]; xEATrade.GetPositions( symbolPeriodPositions, symbol, period); int symbolPeriodPositionsCount = ArraySize(symbolPeriodPositions); if (symbolPeriodPositionsCount <= 0) { return; } // for (int i = 0; i < symbolPeriodPositionsCount; i++) { // XPosition iPosition = symbolPeriodPositions[i]; // ENUM_X_SIGNAL_PROVIDERS iProvider = ExtractProviderFromComment(iPosition.comment); if (iProvider == NONE || iProvider != provider) { continue; } // Add( iPosition, result); } } // // Find Reversal Position Type ... ENUM_POSITION_TYPE GetSupportPositionType(ENUM_POSITION_TYPE type) { // ENUM_POSITION_TYPE result = POSITION_TYPE_BUY; // if (type == POSITION_TYPE_BUY) { result = POSITION_TYPE_SELL; } else { result = POSITION_TYPE_BUY; } // return result; } // // Check a Position Has Supportable or not ... bool IsSupportablePosition(XPosition &position) { // bool result = false; // if (StringLen(position.comment) <= 0) { return result; } // int supStrPos = StringFind( position.comment, mSupportPrefix + "("); // result = supStrPos < 0; // return result; } // // Check a Position has Support Position or not ... bool HasSupportPosition(XPosition &position) { // bool result = false; // int positionsCount = xEATrade.OpenPositionsCount(); // if (positionsCount <= 0 || position.ticket == 0 || StringLen(position.comment) <= 0) { return result; } // string supCommentStr = mSupportPrefix + "(" + (string)position.ticket + ")"; // XPosition positions[]; xEATrade.GetPositions(positions); // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // int supCommentPos = StringFind( iPosition.comment, supCommentStr); // result = supCommentPos >= 0; if (result) { break; } } // return result; } // // Open a Support Position based on Exists ... void OpenSupportPosition(XPosition &position) { // bool isSupportable = IsSupportablePosition(position); if (!isSupportable) { return; } // bool hasSupport = HasSupportPosition(position); if (hasSupport) { return; } // ENUM_POSITION_TYPE type = GetSupportPositionType(position.type); double entry = GetEntry( position.symbol, type); // bool isLong = IsLong(type); // double tpPrice = PipsToPrice( position.symbol, 10); double slPrice = PipsToPrice( position.symbol, 5); // double tp = 0; // isLong // ? entry + tpPrice // : entry - tpPrice; // double sl = 0; // isLong // ? entry - slPrice // : entry + slPrice; // string comment = mSupportPrefix + "(" + (string)position.ticket + ")"; // bool isPositionOpen = false; // // Open Signal Position ... if (isLong) { // isPositionOpen = xEATrade.Buy( position.symbol, position.period, position.volume, entry, sl, tp, comment); } else { // isPositionOpen = xEATrade.Sell( position.symbol, position.period, position.volume, entry, sl, tp, comment); } // if (isPositionOpen) { // LogMessage("Open Support Psition for: " + position.comment); } } // // END Functions ... //