From 818bfdf4f55de27b66d26b07b6ad671733c65faa Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 22 Jul 2024 16:28:10 +0330 Subject: [PATCH] complete trailing ... --- Classes/x-saherelm.xtrade.class.mq5 | 329 +++++++++++++++++++++++++++- Experts/x-test-strategies.ea.mq5 | 16 +- Libraries/x-saherelm.xtrade.lib.mq5 | 20 +- 3 files changed, 358 insertions(+), 7 deletions(-) diff --git a/Classes/x-saherelm.xtrade.class.mq5 b/Classes/x-saherelm.xtrade.class.mq5 index 30d08701..1163fcc5 100644 --- a/Classes/x-saherelm.xtrade.class.mq5 +++ b/Classes/x-saherelm.xtrade.class.mq5 @@ -4100,15 +4100,93 @@ public: mSaveTrades = value; } + // + // Trailling ... + + // + bool AllowTrailStops() + { + return mAllowTrailStops; + } + + // + void AllowTrailStops(bool value) + { + mAllowTrailStops = value; + } + + // + bool IgnoreTPOnTrail() + { + return mIgnoreTPOnTrail; + } + + // + void IgnoreTPOnTrail(bool value) + { + mIgnoreTPOnTrail = value; + } + + // + double TrailStartInPoint() + { + return mTrailStartInPoint; + } + + // + void TrailStartInPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mTrailStartInPoint = value; + } + + // + double TrailStepInPoint() + { + return mTrailStepInPoint; + } + + // + void TrailStepInPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mTrailStepInPoint = value; + } + + // + bool TrailBasedOnProfit() + { + return mTrailBasedOnProfit; + } + + // + void TrailBasedOnProfit(bool value) + { + mTrailBasedOnProfit = value; + } + // // Tools ... // // First Step of Trade Handling ... // Since Must Call when a Signal Executed ... - void AddExecutedSignal( - XSignal &signal, // Executed Signal - double commission = 0 // Commission + void AddData( + XSignal &signal, // Executed Signal + double commission = 0, // Commission + bool forceTrail = false // ) { // @@ -4129,6 +4207,24 @@ public: // item.commission = commission; + // + // Trailling Configuration ... + + // + // Force Trail used to implement Trailing for + // Custom Positions ... + if (mAllowTrailStops || forceTrail) + { + // + item.allowTrailStop = true; + + // + item.ignoreTPOnTrail = mIgnoreTPOnTrail; + item.trailStepInPoint = mTrailStepInPoint; + item.trailStartInPoint = mTrailStartInPoint; + item.trailBasedOnProfit = mTrailBasedOnProfit; + } + // Add(item); @@ -4277,6 +4373,225 @@ public: } } + // + // Do all Protections ... + void HandleProtection() + { + // + int count = Count(); + if (!IsValidSize(count)) + { + return; + } + + // + // Do Hedging ... + + // + // Do Force Closing ... + + // + for (int i = 0; i < count; i++) + { + // + ulong ticket = mData[i].ticket; + double profit = mData[i].profit; + double volume = mData[i].volume; + string symbol = mData[i].symbol; + bool isLong = IsLong(mData[i].type); + ENUM_TIMEFRAMES period = mData[i].period; + double points = GetPoints(mData[i].symbol); + bool ignoreTPOnTrail = mData[i].ignoreTPOnTrail; + double trailStepInPoints = mData[i].trailStepInPoint; + double trailStartInPoint = mData[i].trailStartInPoint; + bool trailBasedOnProfit = mData[i].trailBasedOnProfit; + + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + ticket, + iPosition // + ); + if (!hasPosition) + { + continue; + } + + // + // Trail ... + if (mData[i].allowTrailStop) + { + // + // Do Trail ... + + // + // Only Can Trail if Position In Profit ... + if (profit > 0) + { + // + // Current Profit ... + double profitInPoints = (profit / volume); + + // + // Check Trailling Method ... + if (trailBasedOnProfit) + { + // + // if Trailling Method is Based on Profits Growing + // these Values must Greater than 0 ... + if (trailStartInPoint > 0 && trailStepInPoints > 0) + { + // + double requiredProfit = trailStartInPoint + (mData[i].trailLevel * trailStepInPoints); + bool isProfitPassed = profitInPoints >= requiredProfit; + if (isProfitPassed) + { + // + // Calculate new Level SL ... + double sl = + isLong + ? iPosition.entry + (trailStepInPoints * points) + : iPosition.entry - (trailStepInPoints * points); + sl = NormalizePrice( + sl, + symbol // + ); + + // + // Calculate TP ... + double tp = + ignoreTPOnTrail + ? 0 + : iPosition.tp; + + // + if (sl != iPosition.sl) + { + // + bool isModified = mTrader.Modify( + ticket, + sl, + tp // + ); + if (isModified) + { + // + // Increase Trail Level ... + mData[i].trailLevel++; + + // + string msg = "Position (" + ToString(ticket) + ") Stops in Level: " + ToString(mData[i].trailLevel) + " Trailed Successfully ..."; + Alert(msg); + } + } + } + } + } + else + { + // + // Handle Trailling Based On Bars ... + + // + bool canTrail = true; + if (trailStartInPoint > 0) + { + // + // Check Profit ... + canTrail = profitInPoints >= trailStartInPoint; + } + + // + if (canTrail) + { + // + // Zero Index Bar ... + XOHCL zBar; + bool isInited = zBar.Init( + symbol, + period, + 0 // + ); + if (isInited) + { + // + // Get Previous Bar ... + XOHCL cBar; + isInited = zBar.GetPreviousBar(cBar); + if (isInited) + { + // + // Get Prev of Previous Bar ... + XOHCL pBar; + isInited = cBar.GetPreviousBar(pBar); + if (isInited) + { + // + // Here we have to Check Bar Closes for + // Trailling Stops ... + canTrail = + // + isLong + ? cBar.IsBullish() && + cBar.close > pBar.open + : cBar.IsBearish() && + cBar.close < pBar.open + // + ; + if (canTrail) + { + // + // Calculate new Level SL ... + double sl = + isLong + ? cBar.low + : cBar.high; + sl = NormalizePrice( + sl, + symbol // + ); + + // + // Calculate TP ... + double tp = + ignoreTPOnTrail + ? 0 + : iPosition.tp; + + // + if (sl != iPosition.sl) + { + // + bool isModified = mTrader.Modify( + ticket, + sl, + tp // + ); + if (isModified) + { + // + // Increase Trail Level ... + mData[i].trailLevel++; + + // + string msg = "Position (" + ToString(ticket) + ") Stops in Level: " + ToString(mData[i].trailLevel) + " Trailed Successfully ..."; + Alert(msg); + } + } + } + } + } + } + } + } + } + } + + // + // Grid ... + } + } + // // Protected ... protected: @@ -4291,6 +4606,14 @@ protected: XSCTrade *mTrader; // Instance of Trader Class XTradeCollector *mCollector; // Instance of Trade Collector Class + // + // Trailling ... + bool mAllowTrailStops; // Trail All Trades Stops + bool mIgnoreTPOnTrail; // Ignore SL Trailed TP + bool mTrailBasedOnProfit; // Do Trail Based on Profit Points + double mTrailStartInPoint; // Trail Starts in Points of Profit + double mTrailStepInPoint; // Profit Must Grows Point to do Trailling + // XTradeData mData[]; // Hold Trade Data diff --git a/Experts/x-test-strategies.ea.mq5 b/Experts/x-test-strategies.ea.mq5 index 00ac814b..3e0dec13 100644 --- a/Experts/x-test-strategies.ea.mq5 +++ b/Experts/x-test-strategies.ea.mq5 @@ -225,9 +225,18 @@ bool InitialEA() // eaTradeHandler = new XSCXTradeHandler(eaTrader); + eaTradeHandler.SetAlertPrefix(ShortName + "> TradeHandler"); eaTradeHandler.SaveTrades(true); eaTradeHandler.SaveSignals(true); + // + // Configure Trailing ... + eaTradeHandler.AllowTrailStops(false); + eaTradeHandler.TrailStepInPoint(10); + eaTradeHandler.TrailStartInPoint(30); + eaTradeHandler.IgnoreTPOnTrail(true); + eaTradeHandler.TrailBasedOnProfit(true); + // XSymbolParser symbolParser; @@ -334,11 +343,16 @@ void HandleStrategiesOnTick() } // +// Manage Trading States ... void HandleTradeState() { // // Implement All Trade States here ... eaTradeHandler.UpdateData(); + + // + // Do Protection Senarios ... + eaTradeHandler.HandleProtection(); } // @@ -386,7 +400,7 @@ void OnSignalRecieved(XSignal &signal) // // Add Signal to Trade Handler ... - eaTradeHandler.AddExecutedSignal( + eaTradeHandler.AddData( signal, commission // ); diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index 997c25ba..b13fd517 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -3523,6 +3523,9 @@ struct XTradeData profit = 0; volume = 0; commission = 0; + + // + ResetTrail(); } // @@ -3741,13 +3744,24 @@ struct XTradeData // Trailing Stop .... // - bool canTrail; // Specified Position Can Trail Stop or not + bool allowTrailStop; // Specified Position Can Trail Stop or not + bool ignoreTPOnTrail; // Ignore TP when SL Trailed + bool trailBasedOnProfit; // Do Trail Based on Profit Points + int trailLevel; // Last Trail Level + double trailStartInPoint; // Trail Starts When Profits Growing in Point + double trailStepInPoint; // Profit Must Grows Point to do Trailling // // Reset all Trailing Configurations .... - void ResetTrail() { + void ResetTrail() + { // - canTrail = false; + trailLevel = 0; + trailStepInPoint = 0; + trailStartInPoint = 0; + allowTrailStop = false; + ignoreTPOnTrail = false; + trailBasedOnProfit = false; } //